home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Graphics / Multimedia / MPlay / mpeg_play2.0 / video.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-13  |  100.7 KB  |  3,840 lines

  1. /*
  2.  * Copyright (c) 1992 The Regents of the University of California.
  3.  * All rights reserved.  
  4.  *
  5.  * Permission to use, copy, modify, and distribute this software and its
  6.  * documentation for any purpose, without fee, and without written agreement is
  7.  * hereby granted, provided that the above copyright notice and the following
  8.  * two paragraphs appear in all copies of this software.
  9.  *
  10.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  11.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  12.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  13.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14.  *
  15.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  16.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  17.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  18.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  19.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  20.  */
  21. /* This file contains C code that implements
  22.  * the video decoder model.
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <assert.h>
  28.  
  29. #ifndef MIPS
  30. #include <sys/time.h>
  31. #else
  32. #include <sys/types.h>
  33. #include <sys/system.h>
  34. #endif
  35.  
  36. #include "decoders.h"
  37. #include "video.h"
  38. #include "nextstep.h"
  39. #include "util.h"
  40. #include "proto.h"
  41.  
  42. /* Declarations of functions. */
  43. static void ReconIMBlock();
  44. static void ReconPMBlock();
  45. static void ReconBMBlock();
  46. static void ReconBiMBlock();
  47. static void ReconSkippedBlock();
  48. static void DoPictureDisplay();
  49. static int ParseSeqHead();
  50. static int ParseGOP();
  51. static int ParsePicture();
  52. static int ParseSlice();
  53. static int ParseMacroBlock();
  54. static void ProcessSkippedPFrameMBlocks();
  55. static void ProcessSkippedBFrameMBlocks();
  56.  
  57.  
  58. /* Macro for returning 1 if num is positive, -1 if negative, 0 if 0. */
  59.  
  60. #define Sign(num) ((num > 0) ? 1 : ((num == 0) ? 0 : -1))
  61.  
  62. /* Declare global pointer to vid stream used for current decoding. */
  63.  
  64. VidStream *curVidStream = NULL;
  65.  
  66. /* Set up array for fast conversion from zig zag order to row/column
  67.    coordinates.
  68. */
  69.  
  70. int zigzag[64][2] = {
  71.   0, 0, 1, 0, 0, 1, 0, 2, 1, 1, 2, 0, 3, 0, 2, 1, 1, 2, 0, 3, 0, 4, 1, 3,
  72.   2, 2, 3, 1, 4, 0, 5, 0, 4, 1, 3, 2, 2, 3, 1, 4, 0, 5, 0, 6, 1, 5, 2, 4,
  73.   3, 3, 4, 2, 5, 1, 6, 0, 7, 0, 6, 1, 5, 2, 4, 3, 3, 4, 2, 5, 1, 6, 0, 7,
  74.   1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6, 2, 7, 1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6,
  75.   2, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 5, 7, 6, 6,
  76. 7, 5, 7, 6, 6, 7, 7, 7};
  77. /* Array mapping zigzag to array pointer offset. */
  78.  
  79. int zigzag_direct[64] = {
  80.   0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12,
  81.   19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
  82.   42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
  83. 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63};
  84. /* Set up array for fast conversion from row/column coordinates to
  85.    zig zag order.
  86. */
  87.  
  88. int scan[8][8] = {
  89.   {0, 1, 5, 6, 14, 15, 27, 28},
  90.   {2, 4, 7, 13, 16, 26, 29, 42},
  91.   {3, 8, 12, 17, 25, 30, 41, 43},
  92.   {9, 11, 18, 24, 31, 40, 44, 53},
  93.   {10, 19, 23, 32, 39, 45, 52, 54},
  94.   {20, 22, 33, 38, 46, 51, 55, 60},
  95.   {21, 34, 37, 47, 50, 56, 59, 61},
  96. {35, 36, 48, 49, 57, 58, 62, 63}};
  97. /* Initialize P and B skip flags. */
  98.  
  99. static int No_P_Flag = 0;
  100. static int No_B_Flag = 0;
  101.  
  102. /* Max lum, chrom indices for illegal block checking. */
  103.  
  104. static int lmaxx;
  105. static int lmaxy;
  106. static int cmaxx;
  107. static int cmaxy;
  108.  
  109. /*
  110.  * We use a lookup table to make sure values stay in the 0..255 range.
  111.  * Since this is cropping (ie, x = (x < 0)?0:(x>255)?255:x; ), wee call this
  112.  * table the "crop table".
  113.  * MAX_NEG_CROP is the maximum neg/pos value we can handle.
  114.  */
  115.  
  116. #define MAX_NEG_CROP 384
  117. #define NUM_CROP_ENTRIES (256+2*MAX_NEG_CROP)
  118. #define assertCrop(x)    assert(((x) >= -MAX_NEG_CROP) && \
  119.                    ((x) <= 256+MAX_NEG_CROP))
  120. static unsigned char cropTbl[NUM_CROP_ENTRIES];
  121.  
  122. /*
  123.   The following accounts for time and size  spent in various parsing acitivites
  124.   if ANALYSIS has been defined.
  125. */
  126.  
  127. #ifdef ANALYSIS
  128.  
  129.  
  130. unsigned int bitCount = 0;
  131.  
  132. int showmb_flag = 0;
  133. int showEachFlag = 0;
  134.  
  135. typedef struct {
  136.   int frametype;
  137.   unsigned int totsize;
  138.   unsigned int number;
  139.   unsigned int i_mbsize;
  140.   unsigned int p_mbsize;
  141.   unsigned int b_mbsize;
  142.   unsigned int bi_mbsize;
  143.   unsigned int i_mbnum;
  144.   unsigned int p_mbnum;
  145.   unsigned int b_mbnum;
  146.   unsigned int bi_mbnum;
  147.   unsigned int i_mbcbp[64];
  148.   unsigned int p_mbcbp[64];
  149.   unsigned int b_mbcbp[64];
  150.   unsigned int bi_mbcbp[64];
  151.   unsigned int i_mbcoeff[64];
  152.   unsigned int p_mbcoeff[64];
  153.   unsigned int b_mbcoeff[64];
  154.   unsigned int bi_mbcoeff[64];
  155.   double tottime;
  156. } Statval;
  157.  
  158. Statval stat_a[4];
  159. unsigned int pictureSizeCount;
  160. unsigned int mbSizeCount;
  161. unsigned int *mbCBPPtr, *mbCoeffPtr, *mbSizePtr;
  162. unsigned int cacheHit[8][8];
  163. unsigned int cacheMiss[8][8];
  164.  
  165. static void
  166. init_stat_struct(astat)
  167.   Statval *astat;
  168. {
  169.   int j;
  170.  
  171.   astat->frametype = 0;
  172.   astat->totsize = 0;
  173.   astat->number = 0;
  174.   astat->i_mbsize = 0;
  175.   astat->p_mbsize = 0;
  176.   astat->b_mbsize = 0;
  177.   astat->bi_mbsize = 0;
  178.   astat->i_mbnum = 0;
  179.   astat->p_mbnum = 0;
  180.   astat->b_mbnum = 0;
  181.   astat->bi_mbnum = 0;
  182.  
  183.   for (j = 0; j < 64; j++) {
  184.  
  185.     astat->i_mbcbp[j] = 0;
  186.     astat->p_mbcbp[j] = 0;
  187.     astat->b_mbcbp[j] = 0;
  188.     astat->bi_mbcbp[j] = 0;
  189.     astat->i_mbcoeff[j] = 0;
  190.     astat->p_mbcoeff[j] = 0;
  191.     astat->b_mbcoeff[j] = 0;
  192.     astat->bi_mbcoeff[j] = 0;
  193.   }
  194.   astat->tottime = 0.0;
  195. }
  196.  
  197. void
  198. init_stats()
  199. {
  200.   int i, j;
  201.  
  202.   for (i = 0; i < 4; i++) {
  203.     init_stat_struct(&(stat_a[i]));
  204.     stat_a[i].frametype = i;
  205.   }
  206.  
  207.   for (i = 0; i < 8; i++) {
  208.     for (j = 0; j < 8; j++) {
  209.       cacheHit[i][j] = 0;
  210.       cacheMiss[i][j] = 0;
  211.     }
  212.   }
  213.  
  214.   bitCount = 0;
  215. }
  216.  
  217. static void
  218. PrintOneStat()
  219. {
  220.   int i;
  221.  
  222.   printf("\n");
  223.   switch (stat_a[0].frametype) {
  224.   case I_TYPE:
  225.     printf("I FRAME\n");
  226.     break;
  227.   case P_TYPE:
  228.     printf("P FRAME\n");
  229.     break;
  230.   case B_TYPE:
  231.     printf("B FRAME\n");
  232.     break;
  233.   }
  234.  
  235.   printf("Size: %d bytes + %d bits\n", stat_a[0].totsize / 8, stat_a[0].totsize % 8);
  236.   if (stat_a[0].i_mbnum > 0) {
  237.     printf("\tI Macro Block Stats:\n");
  238.     printf("\t%d I Macroblocks\n", stat_a[0].i_mbnum);
  239.     printf("\tAvg. Size: %d bytes + %d bits\n",
  240.        stat_a[0].i_mbsize / (8 * stat_a[0].i_mbnum),
  241.        (stat_a[0].i_mbsize * stat_a[0].i_mbnum) % 8);
  242.     printf("\t\tCoded Block Pattern Histogram:\n");
  243.     for (i = 0; i < 64; i += 8) {
  244.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].i_mbcbp[i],
  245.          stat_a[0].i_mbcbp[i + 1], stat_a[0].i_mbcbp[i + 2], stat_a[0].i_mbcbp[i + 3],
  246.          stat_a[0].i_mbcbp[i + 4], stat_a[0].i_mbcbp[i + 5], stat_a[0].i_mbcbp[i + 6],
  247.          stat_a[0].i_mbcbp[i + 7]);
  248.     }
  249.     printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  250.     for (i = 0; i < 64; i += 8) {
  251.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].i_mbcoeff[i],
  252.          stat_a[0].i_mbcoeff[i + 1], stat_a[0].i_mbcoeff[i + 2],
  253.          stat_a[0].i_mbcoeff[i + 3], stat_a[0].i_mbcoeff[i + 4],
  254.          stat_a[0].i_mbcoeff[i + 5], stat_a[0].i_mbcoeff[i + 6],
  255.          stat_a[0].i_mbcoeff[i + 7]);
  256.     }
  257.   }
  258.   if (stat_a[0].p_mbnum > 0) {
  259.     printf("\tP Macro Block Stats:\n");
  260.     printf("\t%d P Macroblocks\n", stat_a[0].p_mbnum);
  261.     printf("\tAvg. Size: %d bytes + %d bits\n",
  262.        stat_a[0].p_mbsize / (8 * stat_a[0].p_mbnum),
  263.        (stat_a[0].p_mbsize / stat_a[0].p_mbnum) % 8);
  264.     printf("\t\tCoded Block Pattern Histogram:\n");
  265.     for (i = 0; i < 64; i += 8) {
  266.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].p_mbcbp[i],
  267.          stat_a[0].p_mbcbp[i + 1], stat_a[0].p_mbcbp[i + 2], stat_a[0].p_mbcbp[i + 3],
  268.          stat_a[0].p_mbcbp[i + 4], stat_a[0].p_mbcbp[i + 5], stat_a[0].p_mbcbp[i + 6],
  269.          stat_a[0].p_mbcbp[i + 7]);
  270.     }
  271.     printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  272.     for (i = 0; i < 64; i += 8) {
  273.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].p_mbcoeff[i],
  274.          stat_a[0].p_mbcoeff[i + 1], stat_a[0].p_mbcoeff[i + 2],
  275.          stat_a[0].p_mbcoeff[i + 3], stat_a[0].p_mbcoeff[i + 4],
  276.          stat_a[0].p_mbcoeff[i + 5], stat_a[0].p_mbcoeff[i + 6],
  277.          stat_a[0].p_mbcoeff[i + 7]);
  278.     }
  279.   }
  280.   if (stat_a[0].b_mbnum > 0) {
  281.     printf("\tB Macro Block Stats:\n");
  282.     printf("\t%d B Macroblocks\n", stat_a[0].b_mbnum);
  283.     printf("\tAvg. Size: %d bytes + %d bits\n",
  284.        stat_a[0].b_mbsize / (8 * stat_a[0].b_mbnum),
  285.        (stat_a[0].b_mbsize / stat_a[0].b_mbnum) % 8);
  286.     printf("\t\tCoded Block Pattern Histogram:\n");
  287.     for (i = 0; i < 64; i += 8) {
  288.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].b_mbcbp[i],
  289.          stat_a[0].b_mbcbp[i + 1], stat_a[0].b_mbcbp[i + 2], stat_a[0].b_mbcbp[i + 3],
  290.          stat_a[0].b_mbcbp[i + 4], stat_a[0].b_mbcbp[i + 5], stat_a[0].b_mbcbp[i + 6],
  291.          stat_a[0].b_mbcbp[i + 7]);
  292.     }
  293.     printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  294.     for (i = 0; i < 64; i += 8) {
  295.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].b_mbcoeff[i],
  296.          stat_a[0].b_mbcoeff[i + 1], stat_a[0].b_mbcoeff[i + 2],
  297.          stat_a[0].b_mbcoeff[i + 3], stat_a[0].b_mbcoeff[i + 4],
  298.          stat_a[0].b_mbcoeff[i + 5], stat_a[0].b_mbcoeff[i + 6],
  299.          stat_a[0].b_mbcoeff[i + 7]);
  300.     }
  301.   }
  302.   if (stat_a[0].bi_mbnum > 0) {
  303.     printf("\tBi Macro Block Stats:\n");
  304.     printf("\t%d Bi Macroblocks\n", stat_a[0].bi_mbnum);
  305.     printf("\tAvg. Size: %d bytes + %d bits\n",
  306.        stat_a[0].bi_mbsize / (8 * stat_a[0].bi_mbnum),
  307.        (stat_a[0].bi_mbsize * stat_a[0].bi_mbnum) % 8);
  308.     printf("\t\tCoded Block Pattern Histogram:\n");
  309.     for (i = 0; i < 64; i += 8) {
  310.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].bi_mbcbp[i],
  311.          stat_a[0].bi_mbcbp[i + 1], stat_a[0].bi_mbcbp[i + 2], stat_a[0].bi_mbcbp[i + 3],
  312.          stat_a[0].bi_mbcbp[i + 4], stat_a[0].bi_mbcbp[i + 5], stat_a[0].bi_mbcbp[i + 6],
  313.          stat_a[0].bi_mbcbp[i + 7]);
  314.     }
  315.     printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  316.     for (i = 0; i < 64; i += 8) {
  317.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].bi_mbcoeff[i],
  318.          stat_a[0].bi_mbcoeff[i + 1], stat_a[0].bi_mbcoeff[i + 2],
  319.          stat_a[0].bi_mbcoeff[i + 3], stat_a[0].bi_mbcoeff[i + 4],
  320.          stat_a[0].bi_mbcoeff[i + 5], stat_a[0].bi_mbcoeff[i + 6],
  321.          stat_a[0].bi_mbcoeff[i + 7]);
  322.     }
  323.   }
  324.   printf("\nTime to Decode: %g secs.\n", stat_a[0].tottime);
  325.   printf("****************\n");
  326. }
  327.  
  328. void
  329. PrintAllStats()
  330. {
  331.   int i, j;
  332.   unsigned int supertot, supernum;
  333.   double supertime;
  334.  
  335.   printf("\n");
  336.   printf("General Info: \n");
  337.   printf("Width: %d\nHeight: %d\n", curVidStream->mb_width * 16, curVidStream->mb_height * 16);
  338.  
  339.   for (i = 1; i < 4; i++) {
  340.  
  341.     if (stat_a[i].number == 0)
  342.       continue;
  343.  
  344.     switch (i) {
  345.     case 1:
  346.       printf("I FRAMES\n");
  347.       break;
  348.     case 2:
  349.       printf("P FRAMES\n");
  350.       break;
  351.     case 3:
  352.       printf("B FRAMES\n");
  353.       break;
  354.     }
  355.  
  356.     printf("Number: %d\n", stat_a[i].number);
  357.     printf("Avg. Size: %d bytes + %d bits\n",
  358.        stat_a[i].totsize / (8 * stat_a[i].number), (stat_a[i].totsize / stat_a[i].number) % 8);
  359.     if (stat_a[i].i_mbnum > 0) {
  360.       printf("\tI Macro Block Stats:\n");
  361.       printf("\t%d I Macroblocks\n", stat_a[i].i_mbnum);
  362.       printf("\tAvg. Size: %d bytes + %d bits\n",
  363.          stat_a[i].i_mbsize / (8 * stat_a[i].i_mbnum),
  364.          (stat_a[i].i_mbsize / stat_a[i].i_mbnum) % 8);
  365.       printf("\t\tCoded Block Pattern Histogram:\n");
  366.       for (j = 0; j < 64; j += 8) {
  367.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].i_mbcbp[j],
  368.            stat_a[i].i_mbcbp[j + 1], stat_a[i].i_mbcbp[j + 2], stat_a[i].i_mbcbp[j + 3],
  369.            stat_a[i].i_mbcbp[j + 4], stat_a[i].i_mbcbp[j + 5], stat_a[i].i_mbcbp[j + 6],
  370.            stat_a[i].i_mbcbp[j + 7]);
  371.       }
  372.       printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  373.       for (j = 0; j < 64; j += 8) {
  374.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].i_mbcoeff[j],
  375.            stat_a[i].i_mbcoeff[j + 1], stat_a[i].i_mbcoeff[j + 2],
  376.            stat_a[i].i_mbcoeff[j + 3], stat_a[i].i_mbcoeff[j + 4],
  377.            stat_a[i].i_mbcoeff[j + 5], stat_a[i].i_mbcoeff[j + 6],
  378.            stat_a[i].i_mbcoeff[j + 7]);
  379.       }
  380.     }
  381.     if (stat_a[i].p_mbnum > 0) {
  382.       printf("\tP Macro Block Stats:\n");
  383.       printf("\t%d P Macroblocks\n", stat_a[i].p_mbnum);
  384.       printf("\tAvg. Size: %d bytes + %d bits\n",
  385.          stat_a[i].p_mbsize / (8 * stat_a[i].p_mbnum),
  386.          (stat_a[i].p_mbsize / stat_a[i].p_mbnum) % 8);
  387.       printf("\t\tCoded Block Pattern Histogram:\n");
  388.       for (j = 0; j < 64; j += 8) {
  389.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].p_mbcbp[j],
  390.            stat_a[i].p_mbcbp[j + 1], stat_a[i].p_mbcbp[j + 2], stat_a[i].p_mbcbp[j + 3],
  391.            stat_a[i].p_mbcbp[j + 4], stat_a[i].p_mbcbp[j + 5], stat_a[i].p_mbcbp[j + 6],
  392.            stat_a[i].p_mbcbp[j + 7]);
  393.       }
  394.       printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  395.       for (j = 0; j < 64; j += 8) {
  396.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].p_mbcoeff[j],
  397.            stat_a[i].p_mbcoeff[j + 1], stat_a[i].p_mbcoeff[j + 2],
  398.            stat_a[i].p_mbcoeff[j + 3], stat_a[i].p_mbcoeff[j + 4],
  399.            stat_a[i].p_mbcoeff[j + 5], stat_a[i].p_mbcoeff[j + 6],
  400.            stat_a[i].p_mbcoeff[j + 7]);
  401.       }
  402.     }
  403.     if (stat_a[i].b_mbnum > 0) {
  404.       printf("\tB Macro Block Stats:\n");
  405.       printf("\t%d B Macroblocks\n", stat_a[i].b_mbnum);
  406.       printf("\tAvg. Size: %d bytes + %d bits\n",
  407.          stat_a[i].b_mbsize / (8 * stat_a[i].b_mbnum),
  408.          (stat_a[i].b_mbsize * stat_a[i].b_mbnum) % 8);
  409.       printf("\t\tCoded Block Pattern Histogram:\n");
  410.       for (j = 0; j < 64; j += 8) {
  411.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].b_mbcbp[j],
  412.            stat_a[i].b_mbcbp[j + 1], stat_a[i].b_mbcbp[j + 2], stat_a[i].b_mbcbp[j + 3],
  413.            stat_a[i].b_mbcbp[j + 4], stat_a[i].b_mbcbp[j + 5], stat_a[i].b_mbcbp[j + 6],
  414.            stat_a[i].b_mbcbp[j + 7]);
  415.       }
  416.       printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  417.       for (j = 0; j < 64; j += 8) {
  418.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].b_mbcoeff[j],
  419.            stat_a[i].b_mbcoeff[j + 1], stat_a[i].b_mbcoeff[j + 2],
  420.            stat_a[i].b_mbcoeff[j + 3], stat_a[i].b_mbcoeff[j + 4],
  421.            stat_a[i].b_mbcoeff[j + 5], stat_a[i].b_mbcoeff[j + 6],
  422.            stat_a[i].b_mbcoeff[j + 7]);
  423.       }
  424.     }
  425.     if (stat_a[i].bi_mbnum > 0) {
  426.       printf("\tBi Macro Block Stats:\n");
  427.       printf("\t%d Bi Macroblocks\n", stat_a[i].bi_mbnum);
  428.       printf("\tAvg. Size: %d bytes + %d bits\n",
  429.          stat_a[i].bi_mbsize / (8 * stat_a[i].bi_mbnum),
  430.          (stat_a[i].bi_mbsize * stat_a[i].bi_mbnum) % 8);
  431.       printf("\t\tCoded Block Pattern Histogram:\n");
  432.       for (j = 0; j < 64; j += 8) {
  433.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].bi_mbcbp[j],
  434.            stat_a[i].bi_mbcbp[j + 1], stat_a[i].bi_mbcbp[j + 2], stat_a[i].bi_mbcbp[j + 3],
  435.            stat_a[i].bi_mbcbp[j + 4], stat_a[i].bi_mbcbp[j + 5], stat_a[i].bi_mbcbp[j + 6],
  436.            stat_a[i].bi_mbcbp[j + 7]);
  437.       }
  438.       printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  439.       for (j = 0; j < 64; j += 8) {
  440.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].bi_mbcoeff[j],
  441.            stat_a[i].bi_mbcoeff[j + 1], stat_a[i].bi_mbcoeff[j + 2],
  442.            stat_a[i].bi_mbcoeff[j + 3], stat_a[i].bi_mbcoeff[j + 4],
  443.            stat_a[i].bi_mbcoeff[j + 5], stat_a[i].bi_mbcoeff[j + 6],
  444.            stat_a[i].bi_mbcoeff[j + 7]);
  445.       }
  446.     }
  447.     printf("\nAvg. Time to Decode: %f secs.\n",
  448.        (stat_a[i].tottime / ((double) stat_a[i].number)));
  449.     printf("\n");
  450.     printf("*************************\n\n");
  451.   }
  452.  
  453.   supertot = stat_a[1].totsize + stat_a[2].totsize + stat_a[3].totsize;
  454.   supernum = stat_a[1].number + stat_a[2].number + stat_a[3].number;
  455.   supertime = stat_a[1].tottime + stat_a[2].tottime + stat_a[3].tottime;
  456.  
  457.   printf("Total Number of Frames: %d\n", supernum);
  458.   printf("Avg Frame Size: %d bytes %d bits\n",
  459.      supertot / (8 * supernum), (supertot / supernum) % 8);
  460.   printf("Total Time Decoding: %g secs.\n", supertime);
  461.   printf("Avg Decoding Time/Frame: %g secs.\n", supertime / ((double) supernum));
  462.   printf("Avg Decoding Frames/Sec: %g secs.\n", ((double) supernum) / supertime);
  463.   printf("\n");
  464.  
  465.   printf("Cache Hits/Miss\n");
  466.   for (i = 0; i < 8; i++) {
  467.     printf("%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\n",
  468.        cacheHit[i][0], cacheMiss[i][0], cacheHit[i][1], cacheMiss[i][1],
  469.        cacheHit[i][2], cacheMiss[i][2], cacheHit[i][3], cacheMiss[i][3]);
  470.     printf("%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\n",
  471.        cacheHit[i][4], cacheMiss[i][4], cacheHit[i][5], cacheMiss[i][5],
  472.        cacheHit[i][6], cacheMiss[i][6], cacheHit[i][7], cacheMiss[i][7]);
  473.   }
  474.  
  475. }
  476.  
  477. static void
  478. CollectStats()
  479. {
  480.   int i, j;
  481.  
  482.   i = stat_a[0].frametype;
  483.  
  484.   stat_a[i].totsize += stat_a[0].totsize;
  485.   stat_a[i].number += stat_a[0].number;
  486.   stat_a[i].i_mbsize += stat_a[0].i_mbsize;
  487.   stat_a[i].p_mbsize += stat_a[0].p_mbsize;
  488.   stat_a[i].b_mbsize += stat_a[0].b_mbsize;
  489.   stat_a[i].bi_mbsize += stat_a[0].bi_mbsize;
  490.   stat_a[i].i_mbnum += stat_a[0].i_mbnum;
  491.   stat_a[i].p_mbnum += stat_a[0].p_mbnum;
  492.   stat_a[i].b_mbnum += stat_a[0].b_mbnum;
  493.   stat_a[i].bi_mbnum += stat_a[0].bi_mbnum;
  494.  
  495.   for (j = 0; j < 64; j++) {
  496.  
  497.     stat_a[i].i_mbcbp[j] += stat_a[0].i_mbcbp[j];
  498.     stat_a[i].p_mbcbp[j] += stat_a[0].p_mbcbp[j];
  499.     stat_a[i].b_mbcbp[j] += stat_a[0].b_mbcbp[j];
  500.     stat_a[i].bi_mbcbp[j] += stat_a[0].bi_mbcbp[j];
  501.     stat_a[i].i_mbcoeff[j] += stat_a[0].i_mbcoeff[j];
  502.     stat_a[i].p_mbcoeff[j] += stat_a[0].p_mbcoeff[j];
  503.     stat_a[i].b_mbcoeff[j] += stat_a[0].b_mbcoeff[j];
  504.     stat_a[i].bi_mbcoeff[j] += stat_a[0].bi_mbcoeff[j];
  505.   }
  506.  
  507.   stat_a[i].tottime += stat_a[0].tottime;
  508.  
  509.   init_stat_struct(&(stat_a[0]));
  510. }
  511.  
  512. static unsigned int
  513. bitCountRead()
  514. {
  515.   return bitCount;
  516. }
  517.  
  518. static void
  519. StartTime()
  520. {
  521.   stat_a[0].tottime = ReadSysClock();
  522. }
  523.  
  524. static void
  525. EndTime()
  526. {
  527.   stat_a[0].tottime = ReadSysClock() - stat_a[0].tottime;
  528. }
  529. #endif
  530.  
  531. double realTimeStart;
  532. int totNumFrames = 0;
  533.  
  534. double
  535. ReadSysClock()
  536. {
  537.   struct timeval tv;
  538.   (void) gettimeofday(&tv, (struct timezone *)NULL);
  539.   return (tv.tv_sec + tv.tv_usec / 1000000.0);
  540. }
  541.  
  542. void
  543. PrintTimeInfo()
  544. {
  545.   double spent;
  546.  
  547.   spent = ReadSysClock() - realTimeStart;
  548.  
  549.   if (!quietFlag) {
  550.     printf("\nReal Time Spent (After Initializations): %f secs.\n", spent);
  551.     printf("Total Frames: %d\n", totNumFrames);
  552.     printf("Avg. Frames/Sec: %f\n", ((double) totNumFrames) / spent);
  553.   }
  554. }
  555.  
  556.  
  557.  
  558. /*
  559.  *--------------------------------------------------------------
  560.  *
  561.  * NewVidStream --
  562.  *
  563.  *    Allocates and initializes a VidStream structure. Takes
  564.  *      as parameter requested size for buffer length.
  565.  *
  566.  * Results:
  567.  *    A pointer to the new VidStream structure.
  568.  *
  569.  * Side effects:
  570.  *      None.
  571.  *
  572.  *--------------------------------------------------------------
  573.  */
  574.  
  575. VidStream *
  576. NewVidStream(bufLength)
  577.   int bufLength;
  578. {
  579.   int i, j;
  580.   VidStream *new;
  581.   static unsigned char default_intra_matrix[64] = {
  582.     8, 16, 19, 22, 26, 27, 29, 34,
  583.     16, 16, 22, 24, 27, 29, 34, 37,
  584.     19, 22, 26, 27, 29, 34, 34, 38,
  585.     22, 22, 26, 27, 29, 34, 37, 40,
  586.     22, 26, 27, 29, 32, 35, 40, 48,
  587.     26, 27, 29, 32, 35, 40, 48, 58,
  588.     26, 27, 29, 34, 38, 46, 56, 69,
  589.   27, 29, 35, 38, 46, 56, 69, 83};
  590.  
  591.   /* Check for legal buffer length. */
  592.  
  593.   if (bufLength < 4)
  594.     return NULL;
  595.  
  596.   /* Make buffer length multiple of 4. */
  597.  
  598.   bufLength = (bufLength + 3) >> 2;
  599.  
  600.   /* Allocate memory for new structure. */
  601.  
  602.   new = (VidStream *) malloc(sizeof(VidStream));
  603.  
  604.   /* Initialize pointers to extension and user data. */
  605.  
  606.   new->group.ext_data = new->group.user_data =
  607.     new->picture.extra_info = new->picture.user_data =
  608.     new->picture.ext_data = new->slice.extra_info =
  609.     new->ext_data = new->user_data = NULL;
  610.  
  611.   /* Copy default intra matrix. */
  612.  
  613.   for (i = 0; i < 8; i++) {
  614.     for (j = 0; j < 8; j++) {
  615.       new->intra_quant_matrix[j][i] = default_intra_matrix[i * 8 + j];
  616.     }
  617.   }
  618.  
  619.   /* Initialize crop table. */
  620.  
  621.   for (i = (-MAX_NEG_CROP); i < NUM_CROP_ENTRIES - MAX_NEG_CROP; i++) {
  622.     if (i <= 0) {
  623.       cropTbl[i + MAX_NEG_CROP] = 0;
  624.     } else if (i >= 255) {
  625.       cropTbl[i + MAX_NEG_CROP] = 255;
  626.     } else {
  627.       cropTbl[i + MAX_NEG_CROP] = i;
  628.     }
  629.   }
  630.  
  631.   /* Initialize non intra quantization matrix. */
  632.  
  633.   for (i = 0; i < 8; i++) {
  634.     for (j = 0; j < 8; j++) {
  635.       new->non_intra_quant_matrix[j][i] = 16;
  636.     }
  637.   }
  638.  
  639.   /* Initialize pointers to image spaces. */
  640.  
  641.   new->current = new->past = new->future = NULL;
  642.   for (i = 0; i < RING_BUF_SIZE; i++) {
  643.     new->ring[i] = NULL;
  644.   }
  645.  
  646.   /* Create buffer. */
  647.  
  648.   new->buf_start = (unsigned int *) malloc(bufLength * 4);
  649.  
  650.   /*
  651.    * Set max_buf_length to one less than actual length to deal with messy
  652.    * data without proper seq. end codes.
  653.    */
  654.  
  655.   new->max_buf_length = bufLength - 1;
  656.  
  657.   /* Initialize bitstream i/o fields. */
  658.  
  659.   new->bit_offset = 0;
  660.   new->buf_length = 0;
  661.   new->buffer = new->buf_start;
  662.  
  663.  
  664.   /* Return structure. */
  665.  
  666.   return new;
  667. }
  668.  
  669.  
  670.  
  671. /*
  672.  *--------------------------------------------------------------
  673.  *
  674.  * DestroyVidStream --
  675.  *
  676.  *    Deallocates a VidStream structure.
  677.  *
  678.  * Results:
  679.  *      None.
  680.  *
  681.  * Side effects:
  682.  *    None.
  683.  *
  684.  *--------------------------------------------------------------
  685.  */
  686. extern void DestroyPictImage(PictImage *apictimage);
  687.  
  688. void
  689. DestroyVidStream(astream)
  690.   VidStream *astream;
  691. {
  692.   int i;
  693.  
  694.   if (astream->ext_data != NULL)
  695.     free(astream->ext_data);
  696.  
  697.   if (astream->user_data != NULL)
  698.     free(astream->user_data);
  699.  
  700.   if (astream->group.ext_data != NULL)
  701.     free(astream->group.ext_data);
  702.  
  703.   if (astream->group.user_data != NULL)
  704.     free(astream->group.user_data);
  705.  
  706.   if (astream->picture.extra_info != NULL)
  707.     free(astream->picture.extra_info);
  708.  
  709.   if (astream->picture.ext_data != NULL)
  710.     free(astream->picture.ext_data);
  711.  
  712.   if (astream->picture.user_data != NULL)
  713.     free(astream->picture.user_data);
  714.  
  715.   if (astream->slice.extra_info != NULL)
  716.     free(astream->slice.extra_info);
  717.  
  718.   if (astream->buf_start != NULL)
  719.     free(astream->buf_start);
  720.  
  721.   for (i = 0; i < RING_BUF_SIZE; i++) {
  722.     if (astream->ring[i] != NULL) {
  723.       DestroyPictImage(astream->ring[i]);
  724.       astream->ring[i] = NULL;
  725.     }
  726.   }
  727.  
  728.   free((char *) astream);
  729. }
  730.  
  731.  
  732.  
  733.  
  734. /*
  735.  *--------------------------------------------------------------
  736.  *
  737.  * NewPictImage --
  738.  *
  739.  *    Allocates and initializes a PictImage structure.
  740.  *      The width and height of the image space are passed in
  741.  *      as parameters.
  742.  *
  743.  * Results:
  744.  *    A pointer to the new PictImage structure.
  745.  *
  746.  * Side effects:
  747.  *    None.
  748.  *
  749.  *--------------------------------------------------------------
  750.  */
  751.  
  752. PictImage *
  753. NewPictImage(width, height)
  754.   unsigned int width, height;
  755. {
  756.   PictImage *new;
  757.  
  758.   /* Allocate memory space for new structure. */
  759.  
  760.   new = (PictImage *) malloc(sizeof(PictImage));
  761.  
  762.  
  763.   /* Allocate memory for image spaces. */
  764.  
  765.   /* for full color, we need ... */
  766.  
  767.   new->m_display = (unsigned char *) malloc(width * height * 4 + 16+16);
  768.  
  769.   /* cacheline-aligned the image buffer */
  770.  
  771.   new->display = 15+new->m_display;
  772.   (int)new->display = (int)new->display >> 4;
  773.   (int)new->display = (int)new->display << 4;
  774.  
  775.   new->luminance = (unsigned char *) malloc(width * height);
  776.   new->Cr = (unsigned char *) malloc(width * height / 4);
  777.   new->Cb = (unsigned char *) malloc(width * height / 4);
  778.  
  779.   /* Reset locked flag. */
  780.  
  781.   new->locked = 0;
  782.  
  783.   /* Return pointer to new structure. */
  784.  
  785.   return new;
  786. }
  787.  
  788.  
  789.  
  790. /*
  791.  *--------------------------------------------------------------
  792.  *
  793.  * DestroyPictImage --
  794.  *
  795.  *    Deallocates a PictImage structure.
  796.  *
  797.  * Results:
  798.  *      None.
  799.  *
  800.  * Side effects:
  801.  *    None.
  802.  *
  803.  *--------------------------------------------------------------
  804.  */
  805. void DestroyPictImage(PictImage *apictimage)
  806. {
  807.   if (apictimage->luminance != NULL) {
  808.     free(apictimage->luminance);
  809.   }
  810.   if (apictimage->Cr != NULL) {
  811.     free(apictimage->Cr);
  812.   }
  813.   if (apictimage->Cb != NULL) {
  814.     free(apictimage->Cb);
  815.   }
  816. #ifdef SH_MEM
  817.   if (apictimage->ximage != NULL) {
  818.     XShmDetach(display, &(apictimage->shminfo));
  819.     XDestroyImage(apictimage->ximage);
  820.     shmdt(apictimage->shminfo.shmaddr);
  821.     apictimage->ximage = NULL;
  822.     apictimage->display = NULL;
  823.   }
  824. #endif
  825.  
  826.   if (apictimage->m_display != NULL) {
  827.     free(apictimage->m_display);  /*freeing display causes mem leaks */
  828.   }
  829.   free(apictimage);
  830. }
  831.  
  832.  
  833.  
  834. /*
  835.  *--------------------------------------------------------------
  836.  *
  837.  * mpegVidRsrc --
  838.  *
  839.  *      Parses bit stream until MB_QUANTUM number of
  840.  *      macroblocks have been decoded or current slice or
  841.  *      picture ends, whichever comes first. If the start
  842.  *      of a frame is encountered, the frame is time stamped
  843.  *      with the value passed in time_stamp. If the value
  844.  *      passed in buffer is not null, the video stream buffer
  845.  *      is set to buffer and the length of the buffer is
  846.  *      expected in value passed in through length. The current
  847.  *      video stream is set to vid_stream. If vid_stream
  848.  *      is passed as NULL, a new VidStream structure is created
  849.  *      and initialized and used as the current video stream.
  850.  *
  851.  * Results:
  852.  *      A pointer to the video stream structure used.
  853.  *
  854.  * Side effects:
  855.  *      Bit stream is irreversibly parsed. If a picture is completed,
  856.  *      a function is called to display the frame at the correct time.
  857.  *
  858.  *--------------------------------------------------------------
  859.  */
  860.  
  861. VidStream *
  862. mpegVidRsrc(time_stamp, vid_stream)
  863.   TimeStamp time_stamp;
  864.   VidStream *vid_stream;
  865. {
  866.   static int first = 1;
  867.   unsigned int data;
  868.   int i, status;
  869.  
  870.   /* If vid_stream is null, create new VidStream structure. */
  871.  
  872.   if (vid_stream == NULL) {
  873.     return NULL;
  874.   }
  875.   
  876.   if(doRewind) longjmp(env,1); /* restart */
  877.  
  878.   /*
  879.    * Set global curVidStream to vid_stream. Necessary because bit i/o use
  880.    * curVidStream and are not passed vid_stream. Also set global bitstream
  881.    * parameters.
  882.    */
  883.  
  884.   curVidStream = vid_stream;
  885.   bitOffset = curVidStream->bit_offset;
  886. #ifdef UTIL2
  887.   curBits = *curVidStream->buffer << bitOffset;
  888. #else
  889.   curBits = *curVidStream->buffer;
  890. #endif
  891.   bufLength = curVidStream->buf_length;
  892.   bitBuffer = curVidStream->buffer;
  893.  
  894.   /*
  895.    * If called for the first time, find start code, make sure it is a
  896.    * sequence start code.
  897.    */
  898.  
  899.   if (first) {
  900.     next_start_code();
  901.     show_bits32(data);
  902.     if (data != SEQ_START_CODE) {
  903.       fprintf(stderr, "This is not an MPEG stream.");
  904.       DestroyVidStream(curVidStream);
  905.       exit(1);
  906.     }
  907.     first = 0;
  908.   }
  909.   /* Get next 32 bits (size of start codes). */
  910.  
  911.   show_bits32(data);
  912.  
  913.   /*
  914.    * Process according to start code (or parse macroblock if not a start code
  915.    * at all.
  916.    */
  917.  
  918.   switch (data) {
  919.  
  920.   case SEQ_END_CODE:
  921.  
  922.     /* Display last frame. */
  923.  
  924.     if (vid_stream->future != NULL) {
  925.       vid_stream->current = vid_stream->future;
  926.       if(!loopFlag) holdFrame = 3;
  927.       ExecuteDisplay(vid_stream);
  928.     }
  929.  
  930.   if (!quietFlag && !loopFlag) {
  931.       fprintf(stderr, "\nDone!\n");
  932.   }
  933.  
  934. #ifdef ANALYSIS
  935.     if(!loopFlag) PrintAllStats();
  936. #endif
  937.     if(!loopFlag) PrintTimeInfo();
  938.         
  939.     longjmp(env,1);
  940.     
  941.     /* start over.  User kills program by killing the window */
  942.     break;
  943.  
  944.   case SEQ_START_CODE:
  945.  
  946.     /* Sequence start code. Parse sequence header. */
  947.  
  948.     if (ParseSeqHead(vid_stream) != PARSE_OK)
  949.       goto error;
  950.  
  951.     /*
  952.      * Return after sequence start code so that application above can use
  953.      * info in header.
  954.      */
  955.  
  956.     goto done;
  957.  
  958.   case GOP_START_CODE:
  959.  
  960.     /* Group of Pictures start code. Parse gop header. */
  961.  
  962.     if (ParseGOP(vid_stream) != PARSE_OK)
  963.       goto error;
  964.  
  965.  
  966.   case PICTURE_START_CODE:
  967.  
  968.     /* Picture start code. Parse picture header and first slice header. */
  969.  
  970.     status = ParsePicture(vid_stream, time_stamp);
  971.  
  972.     if (status == SKIP_PICTURE) {
  973.       next_start_code();
  974.       fprintf(stderr, "Skipping picture...");
  975.       while (!next_bits(32, PICTURE_START_CODE)) {
  976.     if (next_bits(32, GOP_START_CODE))
  977.       break;
  978.     else if (next_bits(32, SEQ_END_CODE))
  979.       break;
  980.     flush_bits(24);
  981.     next_start_code();
  982.       }
  983.       fprintf(stderr, "Done.\n");
  984.       goto done;
  985.     } else if (status != PARSE_OK)
  986.       goto error;
  987.  
  988.  
  989.     if (ParseSlice(vid_stream) != PARSE_OK)
  990.       goto error;
  991.     break;
  992.  
  993.   default:
  994.  
  995.     /* Check for slice start code. */
  996.  
  997.     if ((data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE)) {
  998.  
  999.       /* Slice start code. Parse slice header. */
  1000.  
  1001.       if (ParseSlice(vid_stream) != PARSE_OK)
  1002.     goto error;
  1003.     }
  1004.     break;
  1005.   }
  1006.  
  1007.   /* Parse next MB_QUANTUM macroblocks. */
  1008.  
  1009.   for (i = 0; i < MB_QUANTUM; i++) {
  1010.  
  1011.     /* Check to see if actually a startcode and not a macroblock. */
  1012.  
  1013.     if (!next_bits(23, 0x00000000)) {
  1014.  
  1015.       /* Not start code. Parse Macroblock. */
  1016.  
  1017.       if (ParseMacroBlock(vid_stream) != PARSE_OK)
  1018.     goto error;
  1019.  
  1020. #ifdef ANALYSIS
  1021.       if (showmb_flag) {
  1022.     DoDitherImage(vid_stream->current->luminance, vid_stream->current->Cr,
  1023.               vid_stream->current->Cb, vid_stream->current->display,
  1024.               vid_stream->mb_height * 16, vid_stream->mb_width * 16);
  1025.     ExecuteDisplay(vid_stream);
  1026.       }
  1027. #endif
  1028.  
  1029.     } else {
  1030.  
  1031.       /* Not macroblock, actually start code. Get start code. */
  1032.  
  1033.       next_start_code();
  1034.       show_bits32(data);
  1035.  
  1036.       /*
  1037.        * If start code is outside range of slice start codes, frame is
  1038.        * complete, display frame.
  1039.        */
  1040.  
  1041.       if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) {
  1042.  
  1043. #ifdef ANALYSIS
  1044.     EndTime();
  1045.     stat_a[0].totsize += bitCountRead() - pictureSizeCount;
  1046.     if (showEachFlag) {
  1047.       PrintOneStat();
  1048.     };
  1049.  
  1050.     CollectStats();
  1051. #endif
  1052.  
  1053.     DoPictureDisplay(vid_stream);
  1054.       }
  1055.       break;
  1056.     }
  1057.   }
  1058.  
  1059.   /* Return pointer to video stream structure. */
  1060.  
  1061.   goto done;
  1062.  
  1063. error:
  1064.   fprintf(stderr, "Error!!!!\n");
  1065.   next_start_code();
  1066.   //holdFrame = 1;
  1067.   //doRewind = 1;
  1068.   goto done;
  1069.  
  1070. done:
  1071.  
  1072.   /* Copy global bit i/o variables back into vid_stream. */
  1073.  
  1074.   vid_stream->buffer = bitBuffer;
  1075.   vid_stream->buf_length = bufLength;
  1076.   vid_stream->bit_offset = bitOffset;
  1077.  
  1078.   return vid_stream;
  1079.  
  1080. }
  1081.  
  1082.  
  1083.  
  1084. /*
  1085.  *--------------------------------------------------------------
  1086.  *
  1087.  * ParseSeqHead --
  1088.  *
  1089.  *      Assumes bit stream is at the begining of the sequence
  1090.  *      header start code. Parses off the sequence header.
  1091.  *
  1092.  * Results:
  1093.  *      Fills the vid_stream structure with values derived and
  1094.  *      decoded from the sequence header. Allocates the pict image
  1095.  *      structures based on the dimensions of the image space
  1096.  *      found in the sequence header.
  1097.  *
  1098.  * Side effects:
  1099.  *      Bit stream irreversibly parsed off.
  1100.  *
  1101.  *--------------------------------------------------------------
  1102.  */
  1103.  
  1104. static int
  1105. ParseSeqHead(vid_stream)
  1106.   VidStream *vid_stream;
  1107. {
  1108.  
  1109.   unsigned int data;
  1110.   int i;
  1111.  
  1112.   /* Flush off sequence start code. */
  1113.  
  1114.   flush_bits32;
  1115.  
  1116.   /* Get horizontal size of image space. */
  1117.  
  1118.   get_bits12(data);
  1119.   vid_stream->h_size = data;
  1120.  
  1121.   /* Get vertical size of image space. */
  1122.  
  1123.   get_bits12(data);
  1124.   vid_stream->v_size = data;
  1125.  
  1126.   /* Calculate macroblock width and height of image space. */
  1127.  
  1128.   vid_stream->mb_width = (vid_stream->h_size + 15) / 16;
  1129.   vid_stream->mb_height = (vid_stream->v_size + 15) / 16;
  1130.  
  1131.   /* Initialize lmaxx, lmaxy, cmaxx, cmaxy. */
  1132.  
  1133.   lmaxx = vid_stream->mb_width*16-1;
  1134.   lmaxy = vid_stream->mb_height*16-1;
  1135.   cmaxx = vid_stream->mb_width*8-1;
  1136.   cmaxy = vid_stream->mb_height*8-1;
  1137.  
  1138.   /*
  1139.    * Initialize ring buffer of pict images now that dimensions of image space
  1140.    * are known.
  1141.    */
  1142.  
  1143.  
  1144.   if (vid_stream->ring[0] == NULL) {
  1145.     for (i = 0; i < RING_BUF_SIZE; i++) {
  1146.       vid_stream->ring[i] = NewPictImage(vid_stream->mb_width * 16,
  1147.                      vid_stream->mb_height * 16);
  1148.     }
  1149.   }
  1150.  
  1151.   /* Parse of aspect ratio code. */
  1152.  
  1153.   get_bits4(data);
  1154.   vid_stream->aspect_ratio = (unsigned char) data;
  1155.  
  1156.   /* Parse off picture rate code. */
  1157.  
  1158.   get_bits4(data);
  1159.   vid_stream->picture_rate = (unsigned char) data;
  1160.  
  1161.   /* Parse off bit rate. */
  1162.  
  1163.   get_bits18(data);
  1164.   vid_stream->bit_rate = data;
  1165.  
  1166.   /* Flush marker bit. */
  1167.  
  1168.   flush_bits(1);
  1169.  
  1170.   /* Parse off vbv buffer size. */
  1171.  
  1172.   get_bits10(data);
  1173.   vid_stream->vbv_buffer_size = data;
  1174.  
  1175.   /* Parse off contrained parameter flag. */
  1176.  
  1177.   get_bits1(data);
  1178.   if (data) {
  1179.     vid_stream->const_param_flag = TRUE;
  1180.   } else
  1181.     vid_stream->const_param_flag = FALSE;
  1182.  
  1183.   /*
  1184.    * If intra_quant_matrix_flag set, parse off intra quant matrix values.
  1185.    */
  1186.  
  1187.   get_bits1(data);
  1188.   if (data) {
  1189.     for (i = 0; i < 64; i++) {
  1190.       get_bits8(data);
  1191.  
  1192.       vid_stream->intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] =
  1193.     (unsigned char) data;
  1194.     }
  1195.   }
  1196.   /*
  1197.    * If non intra quant matrix flag set, parse off non intra quant matrix
  1198.    * values.
  1199.    */
  1200.  
  1201.   get_bits1(data);
  1202.   if (data) {
  1203.     for (i = 0; i < 64; i++) {
  1204.       get_bits8(data);
  1205.  
  1206.       vid_stream->non_intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] =
  1207.     (unsigned char) data;
  1208.     }
  1209.   }
  1210.   /* Go to next start code. */
  1211.  
  1212.   next_start_code();
  1213.  
  1214.   /*
  1215.    * If next start code is extension start code, parse off extension data.
  1216.    */
  1217.  
  1218.   if (next_bits(32, EXT_START_CODE)) {
  1219.     flush_bits32;
  1220.     if (vid_stream->ext_data != NULL) {
  1221.       free(vid_stream->ext_data);
  1222.       vid_stream->ext_data = NULL;
  1223.     }
  1224.     vid_stream->ext_data = (char *)get_ext_data();
  1225.   }
  1226.   /* If next start code is user start code, parse off user data. */
  1227.  
  1228.   if (next_bits(32, USER_START_CODE)) {
  1229.     flush_bits32;
  1230.     if (vid_stream->user_data != NULL) {
  1231.       free(vid_stream->user_data);
  1232.       vid_stream->user_data = NULL;
  1233.     }
  1234.     vid_stream->user_data = (char *)get_ext_data();
  1235.   }
  1236.   return PARSE_OK;
  1237. }
  1238.  
  1239.  
  1240.  
  1241. /*
  1242.  *--------------------------------------------------------------
  1243.  *
  1244.  * ParseGOP --
  1245.  *
  1246.  *      Parses of group of pictures header from bit stream
  1247.  *      associated with vid_stream.
  1248.  *
  1249.  * Results:
  1250.  *      Values in gop header placed into video stream structure.
  1251.  *
  1252.  * Side effects:
  1253.  *      Bit stream irreversibly parsed.
  1254.  *
  1255.  *--------------------------------------------------------------
  1256.  */
  1257.  
  1258. static int
  1259. ParseGOP(vid_stream)
  1260.   VidStream *vid_stream;
  1261. {
  1262.   unsigned int data;
  1263.  
  1264.   /* Flush group of pictures start code. WWWWWWOOOOOOOSSSSSSHHHHH!!! */
  1265.  
  1266.   flush_bits32;
  1267.  
  1268.   /* Parse off drop frame flag. */
  1269.  
  1270.   get_bits1(data);
  1271.   if (data) {
  1272.     vid_stream->group.drop_flag = TRUE;
  1273.   } else
  1274.     vid_stream->group.drop_flag = FALSE;
  1275.  
  1276.   /* Parse off hour component of time code. */
  1277.  
  1278.   get_bits5(data);
  1279.   vid_stream->group.tc_hours = data;
  1280.  
  1281.   /* Parse off minute component of time code. */
  1282.  
  1283.   get_bits6(data);
  1284.   vid_stream->group.tc_minutes = data;
  1285.  
  1286.   /* Flush marker bit. */
  1287.  
  1288.   flush_bits(1);
  1289.  
  1290.   /* Parse off second component of time code. */
  1291.  
  1292.   get_bits6(data);
  1293.   vid_stream->group.tc_seconds = data;
  1294.  
  1295.   /* Parse off picture count component of time code. */
  1296.  
  1297.   get_bits6(data);
  1298.   vid_stream->group.tc_pictures = data;
  1299.  
  1300.   /* Parse off closed gop and broken link flags. */
  1301.  
  1302.   get_bits2(data);
  1303.   if (data > 1) {
  1304.     vid_stream->group.closed_gop = TRUE;
  1305.     if (data > 2) {
  1306.       vid_stream->group.broken_link = TRUE;
  1307.     } else
  1308.       vid_stream->group.broken_link = FALSE;
  1309.   } else {
  1310.     vid_stream->group.closed_gop = FALSE;
  1311.     if (data) {
  1312.       vid_stream->group.broken_link = TRUE;
  1313.     } else
  1314.       vid_stream->group.broken_link = FALSE;
  1315.   }
  1316.  
  1317.   /* Goto next start code. */
  1318.  
  1319.   next_start_code();
  1320.  
  1321.   /* If next start code is extension data, parse off extension data. */
  1322.  
  1323.   if (next_bits(32, EXT_START_CODE)) {
  1324.     flush_bits32;
  1325.     if (vid_stream->group.ext_data != NULL) {
  1326.       free(vid_stream->group.ext_data);
  1327.       vid_stream->group.ext_data = NULL;
  1328.     }
  1329.     vid_stream->group.ext_data = (char *)get_ext_data();
  1330.   }
  1331.   /* If next start code is user data, parse off user data. */
  1332.  
  1333.   if (next_bits(32, USER_START_CODE)) {
  1334.     flush_bits32;
  1335.     if (vid_stream->group.user_data != NULL) {
  1336.       free(vid_stream->group.user_data);
  1337.       vid_stream->group.user_data = NULL;
  1338.     }
  1339.     vid_stream->group.user_data = (char *)get_ext_data();
  1340.   }
  1341.   return PARSE_OK;
  1342. }
  1343.  
  1344.  
  1345.  
  1346. /*
  1347.  *--------------------------------------------------------------
  1348.  *
  1349.  * ParsePicture --
  1350.  *
  1351.  *      Parses picture header. Marks picture to be presented
  1352.  *      at particular time given a time stamp.
  1353.  *
  1354.  * Results:
  1355.  *      Values from picture header put into video stream structure.
  1356.  *
  1357.  * Side effects:
  1358.  *      Bit stream irreversibly parsed.
  1359.  *
  1360.  *--------------------------------------------------------------
  1361.  */
  1362.  
  1363. static int
  1364. ParsePicture(vid_stream, time_stamp)
  1365.   VidStream *vid_stream;
  1366.   TimeStamp time_stamp;
  1367. {
  1368.   unsigned int data;
  1369.   int i;
  1370.  
  1371.   /* Flush header start code. */
  1372.   flush_bits32;
  1373.  
  1374.   /* Parse off temporal reference. */
  1375.   get_bits10(data);
  1376.   vid_stream->picture.temp_ref = data;
  1377.  
  1378.   /* Parse of picture type. */
  1379.   get_bits3(data);
  1380.   vid_stream->picture.code_type = data;
  1381.  
  1382.   if ((vid_stream->picture.code_type == B_TYPE) &&
  1383.       (No_B_Flag ||
  1384.        (vid_stream->past == NULL) ||
  1385.        (vid_stream->future == NULL)))
  1386.     return SKIP_PICTURE;
  1387.  
  1388.   if ((vid_stream->picture.code_type == P_TYPE) &&
  1389.       (No_P_Flag || (vid_stream->future == NULL)))
  1390.     return SKIP_PICTURE;
  1391.  
  1392. #ifdef ANALYSIS
  1393.   StartTime();
  1394.   stat_a[0].frametype = vid_stream->picture.code_type;
  1395.   stat_a[0].number = 1;
  1396.   stat_a[0].totsize = 45;
  1397.   pictureSizeCount = bitCountRead();
  1398. #endif
  1399.  
  1400.   /* Parse off vbv buffer delay value. */
  1401.   get_bits16(data);
  1402.   vid_stream->picture.vbv_delay = data;
  1403.  
  1404.   /* If P or B type frame... */
  1405.  
  1406.   if ((vid_stream->picture.code_type == 2) || (vid_stream->picture.code_type == 3)) {
  1407.  
  1408.     /* Parse off forward vector full pixel flag. */
  1409.     get_bits1(data);
  1410.     if (data)
  1411.       vid_stream->picture.full_pel_forw_vector = TRUE;
  1412.     else
  1413.       vid_stream->picture.full_pel_forw_vector = FALSE;
  1414.  
  1415.     /* Parse of forw_r_code. */
  1416.     get_bits3(data);
  1417.  
  1418.     /* Decode forw_r_code into forw_r_size and forw_f. */
  1419.  
  1420.     vid_stream->picture.forw_r_size = data - 1;
  1421.     vid_stream->picture.forw_f = (1 << vid_stream->picture.forw_r_size);
  1422.   }
  1423.   /* If B type frame... */
  1424.  
  1425.   if (vid_stream->picture.code_type == 3) {
  1426.  
  1427.     /* Parse off back vector full pixel flag. */
  1428.     get_bits1(data);
  1429.     if (data)
  1430.       vid_stream->picture.full_pel_back_vector = TRUE;
  1431.     else
  1432.       vid_stream->picture.full_pel_back_vector = FALSE;
  1433.  
  1434.     /* Parse off back_r_code. */
  1435.     get_bits3(data);
  1436.  
  1437.     /* Decode back_r_code into back_r_size and back_f. */
  1438.  
  1439.     vid_stream->picture.back_r_size = data - 1;
  1440.     vid_stream->picture.back_f = (1 << vid_stream->picture.back_r_size);
  1441.   }
  1442.   /* Get extra bit picture info. */
  1443.  
  1444.   if (vid_stream->picture.extra_info != NULL) {
  1445.     free(vid_stream->picture.extra_info);
  1446.     vid_stream->picture.extra_info = NULL;
  1447.   }
  1448.   vid_stream->picture.extra_info = (char *)get_extra_bit_info();
  1449.  
  1450.   /* Goto next start code. */
  1451.   next_start_code();
  1452.  
  1453.   /* If start code is extension start code, parse off extension data. */
  1454.  
  1455.   if (next_bits(32, EXT_START_CODE)) {
  1456.     flush_bits32;
  1457.  
  1458.     if (vid_stream->picture.ext_data != NULL) {
  1459.       free(vid_stream->picture.ext_data);
  1460.       vid_stream->picture.ext_data = NULL;
  1461.     }
  1462.     vid_stream->picture.ext_data = (char *)get_ext_data();
  1463.   }
  1464.   /* If start code is user start code, parse off user data. */
  1465.  
  1466.   if (next_bits(32, USER_START_CODE)) {
  1467.     flush_bits32;
  1468.  
  1469.     if (vid_stream->picture.user_data != NULL) {
  1470.       free(vid_stream->picture.user_data);
  1471.       vid_stream->picture.user_data = NULL;
  1472.     }
  1473.     vid_stream->picture.user_data = (char *)get_ext_data();
  1474.   }
  1475.   /* Find a pict image structure in ring buffer not currently locked. */
  1476.  
  1477.   i = 0;
  1478.  
  1479.   while (vid_stream->ring[i]->locked != 0) {
  1480.     if (++i >= RING_BUF_SIZE) {
  1481.       perror("Fatal error. Ring buffer full.");
  1482.       exit(1);
  1483.     }
  1484.   }
  1485.  
  1486.   /* Set current pict image structure to the one just found in ring. */
  1487.  
  1488.   vid_stream->current = vid_stream->ring[i];
  1489.  
  1490.   /* Set time stamp. */
  1491.  
  1492.   vid_stream->current->show_time = time_stamp;
  1493.  
  1494.   /* Reset past macroblock address field. */
  1495.  
  1496.   vid_stream->mblock.past_mb_addr = -1;
  1497.  
  1498.   return PARSE_OK;
  1499. }
  1500.  
  1501.  
  1502.  
  1503. /*
  1504.  *--------------------------------------------------------------
  1505.  *
  1506.  * ParseSlice --
  1507.  *
  1508.  *      Parses off slice header.
  1509.  *
  1510.  * Results:
  1511.  *      Values found in slice header put into video stream structure.
  1512.  *
  1513.  * Side effects:
  1514.  *      Bit stream irreversibly parsed.
  1515.  *
  1516.  *--------------------------------------------------------------
  1517.  */
  1518.  
  1519. static int
  1520. ParseSlice(vid_stream)
  1521.   VidStream *vid_stream;
  1522. {
  1523.   unsigned int data;
  1524.  
  1525.   /* Flush slice start code. */
  1526.  
  1527.   flush_bits(24);
  1528.  
  1529.   /* Parse off slice vertical position. */
  1530.  
  1531.   get_bits8(data);
  1532.   vid_stream->slice.vert_pos = data;
  1533.  
  1534.   /* Parse off quantization scale. */
  1535.  
  1536.   get_bits5(data);
  1537.   vid_stream->slice.quant_scale = data;
  1538.  
  1539.   /* Parse off extra bit slice info. */
  1540.  
  1541.   if (vid_stream->slice.extra_info != NULL) {
  1542.     free(vid_stream->slice.extra_info);
  1543.     vid_stream->slice.extra_info = NULL;
  1544.   }
  1545.   vid_stream->slice.extra_info = (char *)get_extra_bit_info();
  1546.  
  1547.   /* Reset past intrablock address. */
  1548.  
  1549.   vid_stream->mblock.past_intra_addr = -2;
  1550.  
  1551.   /* Reset previous recon motion vectors. */
  1552.  
  1553.   vid_stream->mblock.recon_right_for_prev = 0;
  1554.   vid_stream->mblock.recon_down_for_prev = 0;
  1555.   vid_stream->mblock.recon_right_back_prev = 0;
  1556.   vid_stream->mblock.recon_down_back_prev = 0;
  1557.  
  1558.   /* Reset macroblock address. */
  1559.  
  1560.   vid_stream->mblock.mb_address = ((vid_stream->slice.vert_pos - 1) *
  1561.                    vid_stream->mb_width) - 1;
  1562.  
  1563.   /* Reset past dct dc y, cr, and cb values. */
  1564.  
  1565.   vid_stream->block.dct_dc_y_past = 1024;
  1566.   vid_stream->block.dct_dc_cr_past = 1024;
  1567.   vid_stream->block.dct_dc_cb_past = 1024;
  1568.  
  1569.   return PARSE_OK;
  1570. }
  1571.  
  1572.  
  1573.  
  1574. /*
  1575.  *--------------------------------------------------------------
  1576.  *
  1577.  * ParseMacroBlock --
  1578.  *
  1579.  *      Parseoff macroblock. Reconstructs DCT values. Applies
  1580.  *      inverse DCT, reconstructs motion vectors, calculates and
  1581.  *      set pixel values for macroblock in current pict image
  1582.  *      structure.
  1583.  *
  1584.  * Results:
  1585.  *      Here's where everything really happens. Welcome to the
  1586.  *      heart of darkness.
  1587.  *
  1588.  * Side effects:
  1589.  *      Bit stream irreversibly parsed off.
  1590.  *
  1591.  *--------------------------------------------------------------
  1592.  */
  1593.  
  1594. static int
  1595. ParseMacroBlock(vid_stream)
  1596.   VidStream *vid_stream;
  1597. {
  1598.   int addr_incr;
  1599.   unsigned int data;
  1600.   int mask, i, recon_right_for, recon_down_for, recon_right_back,
  1601.       recon_down_back;
  1602.   int zero_block_flag;
  1603.   BOOLEAN mb_quant, mb_motion_forw, mb_motion_back, mb_pattern;
  1604.   int no_dith_flag = 0;
  1605.  
  1606. #ifdef ANALYSIS
  1607.   mbSizeCount = bitCountRead();
  1608. #endif
  1609.  
  1610.   /*
  1611.    * Parse off macroblock address increment and add to macroblock address.
  1612.    */
  1613.   do {
  1614.     DecodeMBAddrInc(addr_incr);
  1615.     if (addr_incr == MB_ESCAPE) {
  1616.       vid_stream->mblock.mb_address += 33;
  1617.       addr_incr = MB_STUFFING;
  1618.     }
  1619.   } while (addr_incr == MB_STUFFING);
  1620.   vid_stream->mblock.mb_address += addr_incr;
  1621.  
  1622.   if (vid_stream->mblock.mb_address > (vid_stream->mb_height *
  1623.                        vid_stream->mb_width - 1))
  1624.     return SKIP_TO_START_CODE;
  1625.  
  1626.   /*
  1627.    * If macroblocks have been skipped, process skipped macroblocks.
  1628.    */
  1629.  
  1630.   if (vid_stream->mblock.mb_address - vid_stream->mblock.past_mb_addr > 1) {
  1631.     if (vid_stream->picture.code_type == P_TYPE)
  1632.       ProcessSkippedPFrameMBlocks(vid_stream);
  1633.     else if (vid_stream->picture.code_type == B_TYPE)
  1634.       ProcessSkippedBFrameMBlocks(vid_stream);
  1635.   }
  1636.   /* Set past macroblock address to current macroblock address. */
  1637.   vid_stream->mblock.past_mb_addr = vid_stream->mblock.mb_address;
  1638.  
  1639.   /* Based on picture type decode macroblock type. */
  1640.   switch (vid_stream->picture.code_type) {
  1641.   case I_TYPE:
  1642.     DecodeMBTypeI(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1643.           vid_stream->mblock.mb_intra);
  1644.     break;
  1645.  
  1646.   case P_TYPE:
  1647.     DecodeMBTypeP(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1648.           vid_stream->mblock.mb_intra);
  1649.     break;
  1650.  
  1651.   case B_TYPE:
  1652.     DecodeMBTypeB(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1653.           vid_stream->mblock.mb_intra);
  1654.     break;
  1655.   }
  1656.  
  1657.   /* If quantization flag set, parse off new quantization scale. */
  1658.  
  1659.   if (mb_quant == TRUE) {
  1660.     get_bits5(data);
  1661.     vid_stream->slice.quant_scale = data;
  1662.   }
  1663.   /* If forward motion vectors exist... */
  1664.   if (mb_motion_forw == TRUE) {
  1665.  
  1666.     /* Parse off and decode horizontal forward motion vector. */
  1667.     DecodeMotionVectors(vid_stream->mblock.motion_h_forw_code);
  1668.  
  1669.     /* If horiz. forward r data exists, parse off. */
  1670.  
  1671.     if ((vid_stream->picture.forw_f != 1) &&
  1672.     (vid_stream->mblock.motion_h_forw_code != 0)) {
  1673.       get_bitsn(vid_stream->picture.forw_r_size, data);
  1674.       vid_stream->mblock.motion_h_forw_r = data;
  1675.     }
  1676.     /* Parse off and decode vertical forward motion vector. */
  1677.     DecodeMotionVectors(vid_stream->mblock.motion_v_forw_code);
  1678.  
  1679.     /* If vert. forw. r data exists, parse off. */
  1680.  
  1681.     if ((vid_stream->picture.forw_f != 1) &&
  1682.     (vid_stream->mblock.motion_v_forw_code != 0)) {
  1683.       get_bitsn(vid_stream->picture.forw_r_size, data);
  1684.       vid_stream->mblock.motion_v_forw_r = data;
  1685.     }
  1686.   }
  1687.   /* If back motion vectors exist... */
  1688.   if (mb_motion_back == TRUE) {
  1689.  
  1690.     /* Parse off and decode horiz. back motion vector. */
  1691.     DecodeMotionVectors(vid_stream->mblock.motion_h_back_code);
  1692.  
  1693.     /* If horiz. back r data exists, parse off. */
  1694.  
  1695.     if ((vid_stream->picture.back_f != 1) &&
  1696.     (vid_stream->mblock.motion_h_back_code != 0)) {
  1697.       get_bitsn(vid_stream->picture.back_r_size, data);
  1698.       vid_stream->mblock.motion_h_back_r = data;
  1699.     }
  1700.     /* Parse off and decode vert. back motion vector. */
  1701.     DecodeMotionVectors(vid_stream->mblock.motion_v_back_code);
  1702.  
  1703.     /* If vert. back r data exists, parse off. */
  1704.  
  1705.     if ((vid_stream->picture.back_f != 1) &&
  1706.     (vid_stream->mblock.motion_v_back_code != 0)) {
  1707.       get_bitsn(vid_stream->picture.back_r_size, data);
  1708.       vid_stream->mblock.motion_v_back_r = data;
  1709.     }
  1710.   }
  1711. #ifdef ANALYSIS
  1712.   if (vid_stream->mblock.mb_intra) {
  1713.     stat_a[0].i_mbnum++;
  1714.     mbCBPPtr = stat_a[0].i_mbcbp;
  1715.     mbCoeffPtr = stat_a[0].i_mbcoeff;
  1716.     mbSizePtr = &(stat_a[0].i_mbsize);
  1717.   } else if (mb_motion_back && mb_motion_forw) {
  1718.     stat_a[0].bi_mbnum++;
  1719.     mbCBPPtr = stat_a[0].bi_mbcbp;
  1720.     mbCoeffPtr = stat_a[0].bi_mbcoeff;
  1721.     mbSizePtr = &(stat_a[0].bi_mbsize);
  1722.   } else if (mb_motion_back) {
  1723.     stat_a[0].b_mbnum++;
  1724.     mbCBPPtr = stat_a[0].b_mbcbp;
  1725.     mbCoeffPtr = stat_a[0].b_mbcoeff;
  1726.     mbSizePtr = &(stat_a[0].b_mbsize);
  1727.   } else {
  1728.     stat_a[0].p_mbnum++;
  1729.     mbCBPPtr = stat_a[0].p_mbcbp;
  1730.     mbCoeffPtr = stat_a[0].p_mbcoeff;
  1731.     mbSizePtr = &(stat_a[0].p_mbsize);
  1732.   }
  1733. #endif
  1734.  
  1735.   /* If mblock pattern flag set, parse and decode CBP (code block pattern). */
  1736.   if (mb_pattern == TRUE) {
  1737.     DecodeCBP(vid_stream->mblock.cbp);
  1738.   }
  1739.   /* Otherwise, set CBP to zero. */
  1740.   else
  1741.     vid_stream->mblock.cbp = 0;
  1742.  
  1743.  
  1744. #ifdef ANALYSIS
  1745.   mbCBPPtr[vid_stream->mblock.cbp]++;
  1746. #endif
  1747.  
  1748.   /* Reconstruct motion vectors depending on picture type. */
  1749.   if (vid_stream->picture.code_type == P_TYPE) {
  1750.  
  1751.     /*
  1752.      * If no forw motion vectors, reset previous and current vectors to 0.
  1753.      */
  1754.  
  1755.     if (!mb_motion_forw) {
  1756.       recon_right_for = 0;
  1757.       recon_down_for = 0;
  1758.       vid_stream->mblock.recon_right_for_prev = 0;
  1759.       vid_stream->mblock.recon_down_for_prev = 0;
  1760.     }
  1761.     /*
  1762.      * Otherwise, compute new forw motion vectors. Reset previous vectors to
  1763.      * current vectors.
  1764.      */
  1765.  
  1766.     else {
  1767.       ComputeForwVector(&recon_right_for, &recon_down_for);
  1768.     }
  1769.   }
  1770.   if (vid_stream->picture.code_type == B_TYPE) {
  1771.  
  1772.     /* Reset prev. and current vectors to zero if mblock is intracoded. */
  1773.  
  1774.     if (vid_stream->mblock.mb_intra) {
  1775.       vid_stream->mblock.recon_right_for_prev = 0;
  1776.       vid_stream->mblock.recon_down_for_prev = 0;
  1777.       vid_stream->mblock.recon_right_back_prev = 0;
  1778.       vid_stream->mblock.recon_down_back_prev = 0;
  1779.     } else {
  1780.  
  1781.       /* If no forw vectors, current vectors equal prev. vectors. */
  1782.  
  1783.       if (!mb_motion_forw) {
  1784.     recon_right_for = vid_stream->mblock.recon_right_for_prev;
  1785.     recon_down_for = vid_stream->mblock.recon_down_for_prev;
  1786.       }
  1787.       /*
  1788.        * Otherwise compute forw. vectors. Reset prev vectors to new values.
  1789.        */
  1790.  
  1791.       else {
  1792.         ComputeForwVector(&recon_right_for, &recon_down_for);
  1793.       }
  1794.  
  1795.       /* If no back vectors, set back vectors to prev back vectors. */
  1796.  
  1797.       if (!mb_motion_back) {
  1798.     recon_right_back = vid_stream->mblock.recon_right_back_prev;
  1799.     recon_down_back = vid_stream->mblock.recon_down_back_prev;
  1800.       }
  1801.       /* Otherwise compute new vectors and reset prev. back vectors. */
  1802.  
  1803.       else {
  1804.     ComputeBackVector(&recon_right_back, &recon_down_back);
  1805.       }
  1806.  
  1807.       /*
  1808.        * Store vector existance flags in structure for possible skipped
  1809.        * macroblocks to follow.
  1810.        */
  1811.  
  1812.       vid_stream->mblock.bpict_past_forw = mb_motion_forw;
  1813.       vid_stream->mblock.bpict_past_back = mb_motion_back;
  1814.     }
  1815.   }
  1816.  
  1817.   /* For each possible block in macroblock. */
  1818.  
  1819.   {
  1820.     {
  1821.       for (mask = 32, i = 0; i < 6; mask >>= 1, i++) {
  1822.     
  1823.     /* If block exists... */
  1824.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) {
  1825.       zero_block_flag = 0;
  1826.       ParseReconBlock(i);
  1827.     } else {
  1828.       zero_block_flag = 1;
  1829.     }
  1830.     
  1831.     /* If macroblock is intra coded... */
  1832.     if (vid_stream->mblock.mb_intra) {
  1833.       ReconIMBlock(vid_stream, i);
  1834.     } else if (mb_motion_forw && mb_motion_back) {
  1835.       ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1836.             recon_right_back, recon_down_back, zero_block_flag);
  1837.     } else if (mb_motion_forw || (vid_stream->picture.code_type == P_TYPE)) {
  1838.       ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1839.                zero_block_flag);
  1840.     } else if (mb_motion_back) {
  1841.       ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
  1842.                zero_block_flag);
  1843.     }
  1844.       }
  1845.     }
  1846.   }
  1847.  
  1848.   /* If D Type picture, flush marker bit. */
  1849.   if (vid_stream->picture.code_type == 4)
  1850.     flush_bits(1);
  1851.  
  1852.   /* If macroblock was intracoded, set macroblock past intra address. */
  1853.   if (vid_stream->mblock.mb_intra)
  1854.     vid_stream->mblock.past_intra_addr =
  1855.       vid_stream->mblock.mb_address;
  1856.  
  1857. #ifdef ANALYSIS
  1858.   *mbSizePtr += bitCountRead() - mbSizeCount;
  1859. #endif
  1860.   return PARSE_OK;
  1861. }
  1862.  
  1863.  
  1864.  
  1865. /*
  1866.  *--------------------------------------------------------------
  1867.  *
  1868.  * ReconIMBlock --
  1869.  *
  1870.  *    Reconstructs intra coded macroblock.
  1871.  *
  1872.  * Results:
  1873.  *    None.
  1874.  *
  1875.  * Side effects:
  1876.  *    None.
  1877.  *
  1878.  *--------------------------------------------------------------
  1879.  */
  1880.  
  1881. static void
  1882. ReconIMBlock(vid_stream, bnum)
  1883.   VidStream *vid_stream;
  1884.   int bnum;
  1885. {
  1886.   int mb_row, mb_col, row, col, row_size, rr;
  1887.   unsigned char *dest;
  1888.  
  1889.   /* Calculate macroblock row and column from address. */
  1890.  
  1891.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  1892.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  1893.  
  1894.  
  1895.   /* If block is luminance block... */
  1896.  
  1897.   if (bnum < 4) {
  1898.  
  1899.     /* Calculate row and col values for upper left pixel of block. */
  1900.  
  1901.     row = mb_row * 16;
  1902.     col = mb_col * 16;
  1903.     if (bnum > 1)
  1904.       row += 8;
  1905.     if (bnum % 2)
  1906.       col += 8;
  1907.  
  1908.     /* Set dest to luminance plane of current pict image. */
  1909.  
  1910.     dest = vid_stream->current->luminance;
  1911.  
  1912.     /* Establish row size. */
  1913.  
  1914.     row_size = vid_stream->mb_width * 16;
  1915.   }
  1916.   /* Otherwise if block is Cr block... */
  1917.  
  1918.   else if (bnum == 4) {
  1919.  
  1920.     /* Set dest to Cr plane of current pict image. */
  1921.  
  1922.     dest = vid_stream->current->Cr;
  1923.  
  1924.     /* Establish row size. */
  1925.  
  1926.     row_size = vid_stream->mb_width * 8;
  1927.  
  1928.     /* Calculate row,col for upper left pixel of block. */
  1929.  
  1930.     row = mb_row * 8;
  1931.     col = mb_col * 8;
  1932.   }
  1933.   /* Otherwise block is Cb block, and ... */
  1934.  
  1935.   else {
  1936.  
  1937.     /* Set dest to Cb plane of current pict image. */
  1938.  
  1939.     dest = vid_stream->current->Cb;
  1940.  
  1941.     /* Establish row size. */
  1942.  
  1943.     row_size = vid_stream->mb_width * 8;
  1944.  
  1945.     /* Calculate row,col for upper left pixel value of block. */
  1946.  
  1947.     row = mb_row * 8;
  1948.     col = mb_col * 8;
  1949.   }
  1950.  
  1951.   /*
  1952.    * For each pixel in block, set to cropped reconstructed value from inverse
  1953.    * dct.
  1954.    */
  1955.   {
  1956.     short *sp = &vid_stream->block.dct_recon[0][0];
  1957.     unsigned char *cm = cropTbl + MAX_NEG_CROP;
  1958.     dest += row * row_size + col;
  1959.     for (rr = 0; rr < 4; rr++, sp += 16, dest += row_size) {
  1960.       dest[0] = cm[sp[0]];
  1961.       assertCrop(sp[0]);
  1962.       dest[1] = cm[sp[1]];
  1963.       assertCrop(sp[1]);
  1964.       dest[2] = cm[sp[2]];
  1965.       assertCrop(sp[2]);
  1966.       dest[3] = cm[sp[3]];
  1967.       assertCrop(sp[3]);
  1968.       dest[4] = cm[sp[4]];
  1969.       assertCrop(sp[4]);
  1970.       dest[5] = cm[sp[5]];
  1971.       assertCrop(sp[5]);
  1972.       dest[6] = cm[sp[6]];
  1973.       assertCrop(sp[6]);
  1974.       dest[7] = cm[sp[7]];
  1975.       assertCrop(sp[7]);
  1976.  
  1977.       dest += row_size;
  1978.       dest[0] = cm[sp[8]];
  1979.       assertCrop(sp[8]);
  1980.       dest[1] = cm[sp[9]];
  1981.       assertCrop(sp[9]);
  1982.       dest[2] = cm[sp[10]];
  1983.       assertCrop(sp[10]);
  1984.       dest[3] = cm[sp[11]];
  1985.       assertCrop(sp[11]);
  1986.       dest[4] = cm[sp[12]];
  1987.       assertCrop(sp[12]);
  1988.       dest[5] = cm[sp[13]];
  1989.       assertCrop(sp[13]);
  1990.       dest[6] = cm[sp[14]];
  1991.       assertCrop(sp[14]);
  1992.       dest[7] = cm[sp[15]];
  1993.       assertCrop(sp[15]);
  1994.     }
  1995.   }
  1996. }
  1997.  
  1998.  
  1999.  
  2000. /*
  2001.  *--------------------------------------------------------------
  2002.  *
  2003.  * ReconPMBlock --
  2004.  *
  2005.  *    Reconstructs forward predicted macroblocks.
  2006.  *
  2007.  * Results:
  2008.  *      None.
  2009.  *
  2010.  * Side effects:
  2011.  *      None.
  2012.  *
  2013.  *--------------------------------------------------------------
  2014.  */
  2015.  
  2016. static void
  2017. ReconPMBlock(vid_stream, bnum, recon_right_for, recon_down_for, zflag)
  2018.   VidStream *vid_stream;
  2019.   int bnum, recon_right_for, recon_down_for, zflag;
  2020. {
  2021.   int mb_row, mb_col, row, col, row_size, rr;
  2022.   unsigned char *dest, *past;
  2023.   static int right_for, down_for, right_half_for, down_half_for;
  2024.   unsigned char *rindex1, *rindex2;
  2025.   unsigned char *index;
  2026.   short int *blockvals;
  2027.  
  2028. #ifdef LOOSE_MPEG
  2029.   int maxx, maxy;
  2030.   int illegalBlock = 0;
  2031.   int row_start, row_end, rfirst, rlast, col_start, col_end, cfirst, clast;
  2032. #endif
  2033.  
  2034.   /* Calculate macroblock row and column from address. */
  2035.  
  2036.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2037.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2038.  
  2039.   if (bnum < 4) {
  2040.  
  2041.     /* Calculate right_for, down_for motion vectors. */
  2042.  
  2043.     right_for = recon_right_for >> 1;
  2044.     down_for = recon_down_for >> 1;
  2045.     right_half_for = recon_right_for & 0x1;
  2046.     down_half_for = recon_down_for & 0x1;
  2047.  
  2048.     /* Set dest to luminance plane of current pict image. */
  2049.  
  2050.     dest = vid_stream->current->luminance;
  2051.  
  2052.     if (vid_stream->picture.code_type == B_TYPE) {
  2053.       if (vid_stream->past != NULL)
  2054.     past = vid_stream->past->luminance;
  2055.     } else {
  2056.  
  2057.       /* Set predicitive frame to current future frame. */
  2058.  
  2059.       if (vid_stream->future != NULL)
  2060.     past = vid_stream->future->luminance;
  2061.     }
  2062.  
  2063.     /* Establish row size. */
  2064.  
  2065.     row_size = vid_stream->mb_width << 4;
  2066.  
  2067.     /* Calculate row,col of upper left pixel in block. */
  2068.  
  2069.     row = mb_row << 4;
  2070.     col = mb_col << 4;
  2071.     if (bnum > 1)
  2072.       row += 8;
  2073.     if (bnum % 2)
  2074.       col += 8;
  2075.  
  2076. #ifdef LOOSE_MPEG
  2077.     /* Check for block illegality. */
  2078.  
  2079.     maxx = lmaxx; maxy = lmaxy;
  2080.  
  2081.     if (row + down_for + 7 > maxy) illegalBlock |= 0x4;
  2082.     else if (row + down_for < 0)  illegalBlock |= 0x1;
  2083.     
  2084.     if (col + right_for + 7 > maxx) illegalBlock |= 0x2;
  2085.     else if (col + right_for < 0) illegalBlock |= 0x8;
  2086.  
  2087. #endif
  2088.   }
  2089.   /* Otherwise, block is NOT luminance block, ... */
  2090.  
  2091.   else {
  2092.  
  2093.     /* Construct motion vectors. */
  2094.  
  2095.     recon_right_for /= 2;
  2096.     recon_down_for /= 2;
  2097.     right_for = recon_right_for >> 1;
  2098.     down_for = recon_down_for >> 1;
  2099.     right_half_for = recon_right_for & 0x1;
  2100.     down_half_for = recon_down_for & 0x1;
  2101.  
  2102.     /* Establish row size. */
  2103.  
  2104.     row_size = vid_stream->mb_width << 3;
  2105.  
  2106.     /* Calculate row,col of upper left pixel in block. */
  2107.  
  2108.     row = mb_row << 3;
  2109.     col = mb_col << 3;
  2110.  
  2111. #ifdef LOOSE_MPEG
  2112.     /* Check for block illegality. */
  2113.  
  2114.     maxx = cmaxx; maxy = cmaxy;
  2115.  
  2116.     if (row + down_for  + 7 > maxy) illegalBlock |= 0x4;
  2117.     else if (row + down_for < 0) illegalBlock |= 0x1;
  2118.  
  2119.     if (col + right_for  + 7 > maxx) illegalBlock  |= 0x2;
  2120.     else if (col + right_for < 0) illegalBlock |= 0x8;
  2121.  
  2122. #endif
  2123.  
  2124.     /* If block is Cr block... */
  2125.  
  2126.     if (bnum == 4) {
  2127.  
  2128.       /* Set dest to Cr plane of current pict image. */
  2129.  
  2130.       dest = vid_stream->current->Cr;
  2131.  
  2132.       if (vid_stream->picture.code_type == B_TYPE) {
  2133.  
  2134.     if (vid_stream->past != NULL)
  2135.       past = vid_stream->past->Cr;
  2136.       } else {
  2137.     if (vid_stream->future != NULL)
  2138.       past = vid_stream->future->Cr;
  2139.       }
  2140.     }
  2141.     /* Otherwise, block is Cb block... */
  2142.  
  2143.     else {
  2144.  
  2145.       /* Set dest to Cb plane of current pict image. */
  2146.  
  2147.       dest = vid_stream->current->Cb;
  2148.  
  2149.       if (vid_stream->picture.code_type == B_TYPE) {
  2150.     if (vid_stream->past != NULL)
  2151.       past = vid_stream->past->Cb;
  2152.       } else {
  2153.     if (vid_stream->future != NULL)
  2154.       past = vid_stream->future->Cb;
  2155.       }
  2156.     }
  2157.   }
  2158.  
  2159.   /* For each pixel in block... */
  2160.  
  2161. #ifdef LOOSE_MPEG
  2162.  
  2163.   if (illegalBlock) {
  2164.     if (illegalBlock & 0x1) {
  2165.       row_start = 0;
  2166.       row_end = row+down_for+8;
  2167.       rfirst = rlast = 8 - row_end;
  2168.     }
  2169.     else if (illegalBlock & 0x4) {
  2170.       row_start = row + down_for;
  2171.       row_end = maxy+1;
  2172.       rlast = row_end - row_start - 1;
  2173.       rfirst = 0;
  2174.     }
  2175.     else {
  2176.       row_start = row+down_for;
  2177.       row_end = row_start+8;
  2178.       rfirst = 0;
  2179.     }
  2180.  
  2181.     if (illegalBlock & 0x8) {
  2182.       col_start = 0;
  2183.       col_end = col + right_for + 8;
  2184.       cfirst = clast = 8 - col_end;
  2185.     }
  2186.     else if (illegalBlock & 0x2) {
  2187.       col_start = col + right_for;
  2188.       col_end = maxx + 1;
  2189.       clast = col_end - col_start - 1;
  2190.       cfirst = 0;
  2191.     }
  2192.     else {
  2193.       col_start = col + right_for;
  2194.       col_end = col_start + 8;
  2195.       cfirst = 0;
  2196.     }
  2197.  
  2198.     for (rr = row_start; rr < row_end; rr++) {
  2199.       rindex1 = past + (rr * row_size) + col_start;
  2200.       index = dest + ((row + rfirst) * row_size) + col + cfirst;
  2201.       for (cc = col_start; cc < col_end; cc++) {
  2202.     *index++ = *rindex1++;
  2203.       }
  2204.     }
  2205.  
  2206.     if (illegalBlock & 0x1) {
  2207.       for (rr = rlast -1; rr >=0; rr--) {
  2208.     index = dest + ((row + rr) * row_size) + col;
  2209.     rindex1 = dest + ((row + rlast) * row_size) + col;
  2210.     for (cc = 0; cc < 8; cc ++) {
  2211.       *index++ = *rindex1++;
  2212.     }
  2213.       }
  2214.     }
  2215.     else if (illegalBlock & 0x4) {
  2216.       for (rr = rlast+1; rr < 8; rr++) {
  2217.     index = dest + ((row + rr) * row_size) + col;
  2218.     rindex1 = dest + ((row + rlast) * row_size) + col;
  2219.     for (cc = 0; cc < 8; cc ++) {
  2220.       *index++ = *rindex1++;
  2221.     }
  2222.       }
  2223.     }
  2224.  
  2225.     if (illegalBlock & 0x2) {
  2226.       for (cc = clast+1; cc < 8; cc++) {
  2227.     index = dest + (row * row_size) + (col + cc);
  2228.     rindex1 = dest + (row * row_size) + (col + clast);
  2229.     for (rr = 0; rr < 8; rr++) {
  2230.       *index = *rindex1;
  2231.       index += row_size;
  2232.       rindex1 += row_size;
  2233.     }
  2234.       }
  2235.     }
  2236.     else if (illegalBlock & 0x8) {
  2237.       for (cc = clast-1; cc >= 0; cc--) {
  2238.     index = dest + (row * row_size) + (col + cc);
  2239.     rindex1 = dest + (row * row_size) + (col + clast);
  2240.     for (rr = 0; rr < 8; rr++) {
  2241.       *index = *rindex1;
  2242.       index += row_size;
  2243.       rindex1 += row_size;
  2244.     }
  2245.       }
  2246.     }
  2247.  
  2248.     if (!zflag) {
  2249.       for (rr = 0; rr < 8; rr++) {
  2250.     index = dest + (row*row_size) + col;
  2251.     blockvals = &(vid_stream->block.dct_recon[rr][0]);
  2252.     index[0] += blockvals[0];
  2253.     index[1] += blockvals[1];
  2254.     index[2] += blockvals[2];
  2255.     index[3] += blockvals[3];
  2256.     index[4] += blockvals[4];
  2257.     index[5] += blockvals[5];
  2258.     index[6] += blockvals[6];
  2259.     index[7] += blockvals[7];
  2260.       }
  2261.     }
  2262.   }
  2263.   else {
  2264.  
  2265. #endif
  2266.  
  2267.     index = dest + (row * row_size) + col;
  2268.     rindex1 = past + (row + down_for) * row_size + col + right_for;
  2269.     
  2270.     blockvals = &(vid_stream->block.dct_recon[0][0]);
  2271.     
  2272.     /*
  2273.      * Calculate predictive pixel value based on motion vectors and copy to
  2274.      * dest plane.
  2275.      */
  2276.     
  2277.     if ((!down_half_for) && (!right_half_for)) {
  2278.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2279.       if (!zflag)
  2280.     for (rr = 0; rr < 4; rr++) {
  2281.       index[0] = cm[(int) rindex1[0] + (int) blockvals[0]];
  2282.       index[1] = cm[(int) rindex1[1] + (int) blockvals[1]];
  2283.       index[2] = cm[(int) rindex1[2] + (int) blockvals[2]];
  2284.       index[3] = cm[(int) rindex1[3] + (int) blockvals[3]];
  2285.       index[4] = cm[(int) rindex1[4] + (int) blockvals[4]];
  2286.       index[5] = cm[(int) rindex1[5] + (int) blockvals[5]];
  2287.       index[6] = cm[(int) rindex1[6] + (int) blockvals[6]];
  2288.       index[7] = cm[(int) rindex1[7] + (int) blockvals[7]];
  2289.       index += row_size;
  2290.       rindex1 += row_size;
  2291.       
  2292.       index[0] = cm[(int) rindex1[0] + (int) blockvals[8]];
  2293.       index[1] = cm[(int) rindex1[1] + (int) blockvals[9]];
  2294.       index[2] = cm[(int) rindex1[2] + (int) blockvals[10]];
  2295.       index[3] = cm[(int) rindex1[3] + (int) blockvals[11]];
  2296.       index[4] = cm[(int) rindex1[4] + (int) blockvals[12]];
  2297.       index[5] = cm[(int) rindex1[5] + (int) blockvals[13]];
  2298.       index[6] = cm[(int) rindex1[6] + (int) blockvals[14]];
  2299.       index[7] = cm[(int) rindex1[7] + (int) blockvals[15]];
  2300.       blockvals += 16;
  2301.       index += row_size;
  2302.       rindex1 += row_size;
  2303.     }
  2304.       else {
  2305.     if (right_for & 0x1) {
  2306.       /* No alignment, use bye copy */
  2307.       for (rr = 0; rr < 4; rr++) {
  2308.         index[0] = rindex1[0];
  2309.         index[1] = rindex1[1];
  2310.         index[2] = rindex1[2];
  2311.         index[3] = rindex1[3];
  2312.         index[4] = rindex1[4];
  2313.         index[5] = rindex1[5];
  2314.         index[6] = rindex1[6];
  2315.         index[7] = rindex1[7];
  2316.         index += row_size;
  2317.         rindex1 += row_size;
  2318.         
  2319.         index[0] = rindex1[0];
  2320.         index[1] = rindex1[1];
  2321.         index[2] = rindex1[2];
  2322.         index[3] = rindex1[3];
  2323.         index[4] = rindex1[4];
  2324.         index[5] = rindex1[5];
  2325.         index[6] = rindex1[6];
  2326.         index[7] = rindex1[7];
  2327.         index += row_size;
  2328.         rindex1 += row_size;
  2329.       }
  2330.     } else if (right_for & 0x2) {
  2331.       /* Half-word bit aligned, use 16 bit copy */
  2332.       short *src = (short *)rindex1;
  2333.       short *dest = (short *)index;
  2334.       row_size >>= 1;
  2335.       for (rr = 0; rr < 4; rr++) {
  2336.         dest[0] = src[0];
  2337.         dest[1] = src[1];
  2338.         dest[2] = src[2];
  2339.         dest[3] = src[3];
  2340.         dest += row_size;
  2341.         src += row_size;
  2342.         
  2343.         dest[0] = src[0];
  2344.         dest[1] = src[1];
  2345.         dest[2] = src[2];
  2346.         dest[3] = src[3];
  2347.         dest += row_size;
  2348.         src += row_size;
  2349.       }
  2350.     } else {
  2351.       /* Word aligned, use 32 bit copy */
  2352.       int *src = (int *)rindex1;
  2353.       int *dest = (int *)index;
  2354.       row_size >>= 2;
  2355.       for (rr = 0; rr < 4; rr++) {
  2356.         dest[0] = src[0];
  2357.         dest[1] = src[1];
  2358.         dest += row_size;
  2359.         src += row_size;
  2360.         
  2361.         dest[0] = src[0];
  2362.         dest[1] = src[1];
  2363.         dest += row_size;
  2364.         src += row_size;
  2365.       }
  2366.     }
  2367.       }
  2368.     } else {
  2369.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2370.       rindex2 = rindex1 + right_half_for + (down_half_for * row_size);
  2371.       if (!zflag)
  2372.     for (rr = 0; rr < 4; rr++) {
  2373.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[0]];
  2374.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[1]];
  2375.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[2]];
  2376.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[3]];
  2377.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[4]];
  2378.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[5]];
  2379.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[6]];
  2380.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[7]];
  2381.       index += row_size;
  2382.       rindex1 += row_size;
  2383.       rindex2 += row_size;
  2384.       
  2385.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[8]];
  2386.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[9]];
  2387.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[10]];
  2388.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[11]];
  2389.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[12]];
  2390.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[13]];
  2391.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[14]];
  2392.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[15]];
  2393.       blockvals += 16;
  2394.       index += row_size;
  2395.       rindex1 += row_size;
  2396.       rindex2 += row_size;
  2397.     }
  2398.       else
  2399.     for (rr = 0; rr < 4; rr++) {
  2400.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2401.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2402.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2403.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2404.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2405.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2406.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2407.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2408.       index += row_size;
  2409.       rindex1 += row_size;
  2410.       rindex2 += row_size;
  2411.       
  2412.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2413.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2414.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2415.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2416.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2417.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2418.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2419.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2420.       index += row_size;
  2421.       rindex1 += row_size;
  2422.       rindex2 += row_size;
  2423.     }
  2424.     }
  2425.  
  2426. #ifdef LOOSE_MPEG
  2427.   }
  2428. #endif
  2429. }
  2430.  
  2431.  
  2432. /*
  2433.  *--------------------------------------------------------------
  2434.  *
  2435.  * ReconBMBlock --
  2436.  *
  2437.  *    Reconstructs back predicted macroblocks.
  2438.  *
  2439.  * Results:
  2440.  *      None.
  2441.  *
  2442.  * Side effects:
  2443.  *      None.
  2444.  *
  2445.  *--------------------------------------------------------------
  2446.  */
  2447.  
  2448. static void
  2449. ReconBMBlock(vid_stream, bnum, recon_right_back, recon_down_back, zflag)
  2450.   VidStream *vid_stream;
  2451.   int bnum, recon_right_back, recon_down_back, zflag;
  2452. {
  2453.   int mb_row, mb_col, row, col, row_size, rr;
  2454.   unsigned char *dest, *future;
  2455.   int right_back, down_back, right_half_back, down_half_back;
  2456.   unsigned char *rindex1, *rindex2;
  2457.   unsigned char *index;
  2458.   short int *blockvals;
  2459.  
  2460. #ifdef LOOSE_MPEG
  2461.   int illegalBlock = 0;
  2462.   int maxx, maxy;
  2463.   int row_start, row_end, rlast, rfirst, col_start, col_end, clast, cfirst;
  2464. #endif
  2465.  
  2466.   /* Calculate macroblock row and column from address. */
  2467.  
  2468.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2469.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2470.  
  2471.   /* If block is luminance block... */
  2472.  
  2473.   if (bnum < 4) {
  2474.  
  2475.     /* Calculate right_back, down_bakc motion vectors. */
  2476.  
  2477.     right_back = recon_right_back >> 1;
  2478.     down_back = recon_down_back >> 1;
  2479.     right_half_back = recon_right_back & 0x1;
  2480.     down_half_back = recon_down_back & 0x1;
  2481.  
  2482.     /* Set dest to luminance plane of current pict image. */
  2483.  
  2484.     dest = vid_stream->current->luminance;
  2485.  
  2486.     /*
  2487.      * If future frame exists, set future to luminance plane of future frame.
  2488.      */
  2489.  
  2490.     if (vid_stream->future != NULL)
  2491.       future = vid_stream->future->luminance;
  2492.  
  2493.     /* Establish row size. */
  2494.  
  2495.     row_size = vid_stream->mb_width << 4;
  2496.  
  2497.     /* Calculate row,col of upper left pixel in block. */
  2498.  
  2499.     row = mb_row << 4;
  2500.     col = mb_col << 4;
  2501.     if (bnum > 1)
  2502.       row += 8;
  2503.     if (bnum % 2)
  2504.       col += 8;
  2505.  
  2506. #ifdef LOOSE_MPEG
  2507.  
  2508.     /* Check for block illegality. */
  2509.  
  2510.     maxx = lmaxx; maxy = lmaxy;
  2511.  
  2512.     if (row + down_back + 7 > maxy) illegalBlock |= 0x4;
  2513.     else if (row + down_back < 0)  illegalBlock |= 0x1;
  2514.     
  2515.     if (col + right_back + 7 > maxx) illegalBlock |= 0x2;
  2516.     else if (col + right_back < 0) illegalBlock |= 0x8;
  2517.  
  2518. #endif
  2519.  
  2520.   }
  2521.   /* Otherwise, block is NOT luminance block, ... */
  2522.  
  2523.   else {
  2524.  
  2525.     /* Construct motion vectors. */
  2526.  
  2527.     recon_right_back /= 2;
  2528.     recon_down_back /= 2;
  2529.     right_back = recon_right_back >> 1;
  2530.     down_back = recon_down_back >> 1;
  2531.     right_half_back = recon_right_back & 0x1;
  2532.     down_half_back = recon_down_back & 0x1;
  2533.  
  2534.     /* Establish row size. */
  2535.  
  2536.     row_size = vid_stream->mb_width << 3;
  2537.  
  2538.     /* Calculate row,col of upper left pixel in block. */
  2539.  
  2540.     row = mb_row << 3;
  2541.     col = mb_col << 3;
  2542.  
  2543. #ifdef LOOSE_MPEG
  2544.  
  2545.     /* Check for block illegality. */
  2546.  
  2547.     maxx = cmaxx; maxy = cmaxy;
  2548.  
  2549.     if (row + down_back + 7 > maxy) illegalBlock |= 0x4;
  2550.     else if (row + down_back < 0) illegalBlock |= 0x1;
  2551.  
  2552.     if (col + right_back + 7 > maxx) illegalBlock  |= 0x2;
  2553.     else if (col + right_back < 0) illegalBlock |= 0x8;
  2554.  
  2555. #endif
  2556.  
  2557.     /* If block is Cr block... */
  2558.  
  2559.     if (bnum == 4) {
  2560.  
  2561.       /* Set dest to Cr plane of current pict image. */
  2562.  
  2563.       dest = vid_stream->current->Cr;
  2564.  
  2565.       /*
  2566.        * If future frame exists, set future to Cr plane of future image.
  2567.        */
  2568.  
  2569.       if (vid_stream->future != NULL)
  2570.     future = vid_stream->future->Cr;
  2571.     }
  2572.     /* Otherwise, block is Cb block... */
  2573.  
  2574.     else {
  2575.  
  2576.       /* Set dest to Cb plane of current pict image. */
  2577.  
  2578.       dest = vid_stream->current->Cb;
  2579.  
  2580.       /*
  2581.        * If future frame exists, set future to Cb plane of future frame.
  2582.        */
  2583.  
  2584.       if (vid_stream->future != NULL)
  2585.     future = vid_stream->future->Cb;
  2586.     }
  2587.   }
  2588.  
  2589.   /* For each pixel in block do... */
  2590.  
  2591. #ifdef LOOSE_MPEG
  2592.  
  2593.   if (illegalBlock) {
  2594.     if (illegalBlock & 0x1) {
  2595.       row_start = 0;
  2596.       row_end = row+down_back+8;
  2597.       rfirst = rlast = 8 - row_end;
  2598.     }
  2599.     else if (illegalBlock & 0x4) {
  2600.       row_start = row + down_back;
  2601.       row_end = maxy+1;
  2602.       rlast = row_end - row_start - 1;
  2603.       rfirst = 0;
  2604.     }
  2605.     else {
  2606.       row_start = row+down_back;
  2607.       row_end = row_start+8;
  2608.       rfirst = 0;
  2609.     }
  2610.  
  2611.     if (illegalBlock & 0x8) {
  2612.       col_start = 0;
  2613.       col_end = col + right_back + 8;
  2614.       cfirst = clast = 8 - col_end;
  2615.     }
  2616.     else if (illegalBlock & 0x2) {
  2617.       col_start = col + right_back;
  2618.       col_end = maxx + 1;
  2619.       clast = col_end - col_start - 1;
  2620.       cfirst = 0;
  2621.     }
  2622.     else {
  2623.       col_start = col + right_back;
  2624.       col_end = col_start + 8;
  2625.       cfirst = 0;
  2626.     }
  2627.  
  2628.     for (rr = row_start; rr < row_end; rr++) {
  2629.       rindex1 = future + (rr * row_size) + col_start;
  2630.       index = dest + ((row + rfirst) * row_size) + col + cfirst;
  2631.       for (cc = col_start; cc < col_end; cc++) {
  2632.     *index++ = *rindex1++;
  2633.       }
  2634.     }
  2635.  
  2636.     if (illegalBlock & 0x1) {
  2637.       for (rr = rlast -1; rr >=0; rr--) {
  2638.     index = dest + ((row + rr) * row_size) + col;
  2639.     rindex1 = dest + ((row + rlast) * row_size) + col;
  2640.     for (cc = 0; cc < 8; cc ++) {
  2641.       *index++ = *rindex1++;
  2642.     }
  2643.       }
  2644.     }
  2645.     else if (illegalBlock & 0x4) {
  2646.       for (rr = rlast+1; rr < 8; rr++) {
  2647.     index = dest + ((row + rr) * row_size) + col;
  2648.     rindex1 = dest + ((row + rlast) * row_size) + col;
  2649.     for (cc = 0; cc < 8; cc ++) {
  2650.       *index++ = *rindex1++;
  2651.     }
  2652.       }
  2653.     }
  2654.  
  2655.     if (illegalBlock & 0x2) {
  2656.       for (cc = clast+1; cc < 8; cc++) {
  2657.     index = dest + (row * row_size) + (col + cc);
  2658.     rindex1 = dest + (row * row_size) + (col + clast);
  2659.     for (rr = 0; rr < 8; rr++) {
  2660.       *index = *rindex1;
  2661.       index += row_size;
  2662.       rindex1 += row_size;
  2663.     }
  2664.       }
  2665.     }
  2666.     else if (illegalBlock & 0x8) {
  2667.       for (cc = clast-1; cc >= 0; cc--) {
  2668.     index = dest + (row * row_size) + (col + cc);
  2669.     rindex1 = dest + (row * row_size) + (col + clast);
  2670.     for (rr = 0; rr < 8; rr++) {
  2671.       *index = *rindex1;
  2672.       index += row_size;
  2673.       rindex1 += row_size;
  2674.     }
  2675.       }
  2676.     }
  2677.  
  2678.     if (!zflag) {
  2679.       for (rr = 0; rr < 8; rr++) {
  2680.     index = dest + (row*row_size) + col;
  2681.     blockvals = &(vid_stream->block.dct_recon[rr][0]);
  2682.     index[0] += blockvals[0];
  2683.     index[1] += blockvals[1];
  2684.     index[2] += blockvals[2];
  2685.     index[3] += blockvals[3];
  2686.     index[4] += blockvals[4];
  2687.     index[5] += blockvals[5];
  2688.     index[6] += blockvals[6];
  2689.     index[7] += blockvals[7];
  2690.       }
  2691.     }
  2692.   }
  2693.   else {
  2694.  
  2695. #endif
  2696.     
  2697.     index = dest + (row * row_size) + col;
  2698.     rindex1 = future + (row + down_back) * row_size + col + right_back;
  2699.  
  2700.     blockvals = &(vid_stream->block.dct_recon[0][0]);
  2701.  
  2702.     if ((!right_half_back) && (!down_half_back)) {
  2703.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2704.       if (!zflag)
  2705.     for (rr = 0; rr < 4; rr++) {
  2706.       index[0] = cm[(int) rindex1[0] + (int) blockvals[0]];
  2707.       index[1] = cm[(int) rindex1[1] + (int) blockvals[1]];
  2708.       index[2] = cm[(int) rindex1[2] + (int) blockvals[2]];
  2709.       index[3] = cm[(int) rindex1[3] + (int) blockvals[3]];
  2710.       index[4] = cm[(int) rindex1[4] + (int) blockvals[4]];
  2711.       index[5] = cm[(int) rindex1[5] + (int) blockvals[5]];
  2712.       index[6] = cm[(int) rindex1[6] + (int) blockvals[6]];
  2713.       index[7] = cm[(int) rindex1[7] + (int) blockvals[7]];
  2714.       index += row_size;
  2715.       rindex1 += row_size;
  2716.       
  2717.       index[0] = cm[(int) rindex1[0] + (int) blockvals[8]];
  2718.       index[1] = cm[(int) rindex1[1] + (int) blockvals[9]];
  2719.       index[2] = cm[(int) rindex1[2] + (int) blockvals[10]];
  2720.       index[3] = cm[(int) rindex1[3] + (int) blockvals[11]];
  2721.       index[4] = cm[(int) rindex1[4] + (int) blockvals[12]];
  2722.       index[5] = cm[(int) rindex1[5] + (int) blockvals[13]];
  2723.       index[6] = cm[(int) rindex1[6] + (int) blockvals[14]];
  2724.       index[7] = cm[(int) rindex1[7] + (int) blockvals[15]];
  2725.       blockvals += 16;
  2726.       index += row_size;
  2727.       rindex1 += row_size;
  2728.     }
  2729.       else {
  2730.     if (right_back & 0x1) {
  2731.       /* No alignment, use bye copy */
  2732.       for (rr = 0; rr < 4; rr++) {
  2733.         index[0] = rindex1[0];
  2734.         index[1] = rindex1[1];
  2735.         index[2] = rindex1[2];
  2736.         index[3] = rindex1[3];
  2737.         index[4] = rindex1[4];
  2738.         index[5] = rindex1[5];
  2739.         index[6] = rindex1[6];
  2740.         index[7] = rindex1[7];
  2741.         index += row_size;
  2742.         rindex1 += row_size;
  2743.         
  2744.         index[0] = rindex1[0];
  2745.         index[1] = rindex1[1];
  2746.         index[2] = rindex1[2];
  2747.         index[3] = rindex1[3];
  2748.         index[4] = rindex1[4];
  2749.         index[5] = rindex1[5];
  2750.         index[6] = rindex1[6];
  2751.         index[7] = rindex1[7];
  2752.         index += row_size;
  2753.         rindex1 += row_size;
  2754.       }
  2755.     } else if (right_back & 0x2) {
  2756.       /* Half-word bit aligned, use 16 bit copy */
  2757.       short *src = (short *)rindex1;
  2758.       short *dest = (short *)index;
  2759.       row_size >>= 1;
  2760.       for (rr = 0; rr < 4; rr++) {
  2761.         dest[0] = src[0];
  2762.         dest[1] = src[1];
  2763.         dest[2] = src[2];
  2764.         dest[3] = src[3];
  2765.         dest += row_size;
  2766.         src += row_size;
  2767.         
  2768.         dest[0] = src[0];
  2769.         dest[1] = src[1];
  2770.         dest[2] = src[2];
  2771.         dest[3] = src[3];
  2772.         dest += row_size;
  2773.         src += row_size;
  2774.       }
  2775.     } else {
  2776.       /* Word aligned, use 32 bit copy */
  2777.       int *src = (int *)rindex1;
  2778.       int *dest = (int *)index;
  2779.       row_size >>= 2;
  2780.       for (rr = 0; rr < 4; rr++) {
  2781.         dest[0] = src[0];
  2782.         dest[1] = src[1];
  2783.         dest += row_size;
  2784.         src += row_size;
  2785.         
  2786.         dest[0] = src[0];
  2787.         dest[1] = src[1];
  2788.         dest += row_size;
  2789.         src += row_size;
  2790.       }
  2791.     }
  2792.       }
  2793.     } else {
  2794.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2795.       rindex2 = rindex1 + right_half_back + (down_half_back * row_size);
  2796.       if (!zflag)
  2797.     for (rr = 0; rr < 4; rr++) {
  2798.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[0]];
  2799.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[1]];
  2800.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[2]];
  2801.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[3]];
  2802.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[4]];
  2803.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[5]];
  2804.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[6]];
  2805.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[7]];
  2806.       index += row_size;
  2807.       rindex1 += row_size;
  2808.       rindex2 += row_size;
  2809.       
  2810.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[8]];
  2811.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[9]];
  2812.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[10]];
  2813.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[11]];
  2814.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[12]];
  2815.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[13]];
  2816.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[14]];
  2817.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[15]];
  2818.       blockvals += 16;
  2819.       index += row_size;
  2820.       rindex1 += row_size;
  2821.       rindex2 += row_size;
  2822.     }
  2823.       else
  2824.     for (rr = 0; rr < 4; rr++) {
  2825.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2826.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2827.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2828.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2829.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2830.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2831.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2832.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2833.       index += row_size;
  2834.       rindex1 += row_size;
  2835.       rindex2 += row_size;
  2836.       
  2837.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2838.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2839.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2840.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2841.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2842.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2843.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2844.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2845.       index += row_size;
  2846.       rindex1 += row_size;
  2847.       rindex2 += row_size;
  2848.     }
  2849.     }
  2850.  
  2851. #ifdef LOOSE_MPEG
  2852.   }
  2853. #endif
  2854.  
  2855. }
  2856.  
  2857.  
  2858. /*
  2859.  *--------------------------------------------------------------
  2860.  *
  2861.  * ReconBiMBlock --
  2862.  *
  2863.  *    Reconstructs bidirectionally predicted macroblocks.
  2864.  *
  2865.  * Results:
  2866.  *      None.
  2867.  *
  2868.  * Side effects:
  2869.  *      None.
  2870.  *
  2871.  *--------------------------------------------------------------
  2872.  */
  2873.  
  2874. static void
  2875. ReconBiMBlock(vid_stream, bnum, recon_right_for, recon_down_for,
  2876.           recon_right_back, recon_down_back, zflag)
  2877.   VidStream *vid_stream;
  2878.   int bnum, recon_right_for, recon_down_for, recon_right_back, recon_down_back;
  2879.   int zflag;
  2880. {
  2881.   int mb_row, mb_col, row, col, row_size, rr;
  2882.   unsigned char *dest, *past, *future;
  2883.   int right_for, down_for, right_half_for, down_half_for;
  2884.   int right_back, down_back, right_half_back, down_half_back;
  2885.   unsigned char *index, *rindex1, *bindex1;
  2886.   short int *blockvals;
  2887.   int forw_row_start, back_row_start, forw_col_start, back_col_start;
  2888.  
  2889. #ifdef LOOSE_MPEG
  2890.   int illegal_forw = 0;
  2891.   int illegal_back = 0;
  2892. #endif
  2893.  
  2894.   /* Calculate macroblock row and column from address. */
  2895.  
  2896.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2897.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2898.  
  2899.   /* If block is luminance block... */
  2900.  
  2901.   if (bnum < 4) {
  2902.  
  2903.     /*
  2904.      * Calculate right_for, down_for, right_half_for, down_half_for,
  2905.      * right_back, down_bakc, right_half_back, and down_half_back, motion
  2906.      * vectors.
  2907.      */
  2908.  
  2909.     right_for = recon_right_for >> 1;
  2910.     down_for = recon_down_for >> 1;
  2911.     right_half_for = recon_right_for & 0x1;
  2912.     down_half_for = recon_down_for & 0x1;
  2913.  
  2914.     right_back = recon_right_back >> 1;
  2915.     down_back = recon_down_back >> 1;
  2916.     right_half_back = recon_right_back & 0x1;
  2917.     down_half_back = recon_down_back & 0x1;
  2918.  
  2919.     /* Set dest to luminance plane of current pict image. */
  2920.  
  2921.     dest = vid_stream->current->luminance;
  2922.  
  2923.     /* If past frame exists, set past to luminance plane of past frame. */
  2924.  
  2925.     if (vid_stream->past != NULL)
  2926.       past = vid_stream->past->luminance;
  2927.  
  2928.     /*
  2929.      * If future frame exists, set future to luminance plane of future frame.
  2930.      */
  2931.  
  2932.     if (vid_stream->future != NULL)
  2933.       future = vid_stream->future->luminance;
  2934.  
  2935.     /* Establish row size. */
  2936.  
  2937.     row_size = (vid_stream->mb_width << 4);
  2938.  
  2939.     /* Calculate row,col of upper left pixel in block. */
  2940.  
  2941.     row = (mb_row << 4);
  2942.     col = (mb_col << 4);
  2943.     if (bnum > 1)
  2944.       row += 8;
  2945.     if (bnum & 0x01)
  2946.       col += 8;
  2947.  
  2948.     forw_col_start = col + right_for;
  2949.     forw_row_start = row + down_for;
  2950.  
  2951.     back_col_start = col + right_back;
  2952.     back_row_start = row + down_back;
  2953.  
  2954. #ifdef LOOSE_MPEG
  2955.  
  2956.     /* Check for illegal pred. blocks. */
  2957.  
  2958.  
  2959.     if (forw_col_start+8 > lmaxx) illegal_forw = 1;
  2960.     else if (forw_col_start < 0) illegal_forw = 1;
  2961.  
  2962.     if (forw_row_start+8 > lmaxy) illegal_forw = 1;
  2963.     else if (forw_row_start < 0) illegal_forw = 1;
  2964.  
  2965.     if (back_col_start+8 > lmaxx) illegal_back = 1;
  2966.     else if (back_col_start < 0) illegal_back = 1;
  2967.  
  2968.     if (back_row_start+8 > lmaxy) illegal_back = 1;
  2969.     else if (back_row_start < 0) illegal_back = 1;
  2970.  
  2971. #endif
  2972.  
  2973.   }
  2974.   /* Otherwise, block is NOT luminance block, ... */
  2975.  
  2976.   else {
  2977.  
  2978.     /* Construct motion vectors. */
  2979.  
  2980.     recon_right_for /= 2;
  2981.     recon_down_for /= 2;
  2982.     right_for = recon_right_for >> 1;
  2983.     down_for = recon_down_for >> 1;
  2984.     right_half_for = recon_right_for & 0x1;
  2985.     down_half_for = recon_down_for & 0x1;
  2986.  
  2987.     recon_right_back /= 2;
  2988.     recon_down_back /= 2;
  2989.     right_back = recon_right_back >> 1;
  2990.     down_back = recon_down_back >> 1;
  2991.     right_half_back = recon_right_back & 0x1;
  2992.     down_half_back = recon_down_back & 0x1;
  2993.  
  2994.     /* Establish row size. */
  2995.  
  2996.     row_size = (vid_stream->mb_width << 3);
  2997.  
  2998.     /* Calculate row,col of upper left pixel in block. */
  2999.  
  3000.     row = (mb_row << 3);
  3001.     col = (mb_col << 3);
  3002.  
  3003.     forw_col_start = col + right_for;
  3004.     forw_row_start = row + down_for;
  3005.  
  3006.     back_col_start = col + right_back;
  3007.     back_row_start = row + down_back;
  3008.  
  3009. #ifdef LOOSE_MPEG
  3010.  
  3011.     /* Check for illegal pred. blocks. */
  3012.  
  3013.     if (forw_col_start+8 > cmaxx) illegal_forw = 1;
  3014.     else if (forw_col_start < 0) illegal_forw = 1;
  3015.  
  3016.     if (forw_row_start+8 > cmaxy) illegal_forw = 1;
  3017.     else if (forw_row_start < 0) illegal_forw = 1;
  3018.  
  3019.     if (back_col_start+8 > cmaxx) illegal_back = 1;
  3020.     else if (back_col_start < 0) illegal_back = 1;
  3021.     
  3022.     if (back_row_start+8 > cmaxy) illegal_back = 1;
  3023.     else if (back_row_start < 0) illegal_back = 1;
  3024.  
  3025. #endif
  3026.     
  3027.     /* If block is Cr block... */
  3028.  
  3029.     if (bnum == 4) {
  3030.  
  3031.       /* Set dest to Cr plane of current pict image. */
  3032.  
  3033.       dest = vid_stream->current->Cr;
  3034.  
  3035.       /* If past frame exists, set past to Cr plane of past image. */
  3036.  
  3037.       if (vid_stream->past != NULL)
  3038.     past = vid_stream->past->Cr;
  3039.  
  3040.       /*
  3041.        * If future frame exists, set future to Cr plane of future image.
  3042.        */
  3043.  
  3044.       if (vid_stream->future != NULL)
  3045.     future = vid_stream->future->Cr;
  3046.     }
  3047.     /* Otherwise, block is Cb block... */
  3048.  
  3049.     else {
  3050.  
  3051.       /* Set dest to Cb plane of current pict image. */
  3052.  
  3053.       dest = vid_stream->current->Cb;
  3054.  
  3055.       /* If past frame exists, set past to Cb plane of past frame. */
  3056.  
  3057.       if (vid_stream->past != NULL)
  3058.     past = vid_stream->past->Cb;
  3059.  
  3060.       /*
  3061.        * If future frame exists, set future to Cb plane of future frame.
  3062.        */
  3063.  
  3064.       if (vid_stream->future != NULL)
  3065.     future = vid_stream->future->Cb;
  3066.     }
  3067.   }
  3068.  
  3069.   /* For each pixel in block... */
  3070.  
  3071.   index = dest + (row * row_size) + col;
  3072.  
  3073. #ifdef LOOSE_MPEG
  3074.   if (illegal_forw) 
  3075.     rindex1 = future + back_row_start * row_size + back_col_start;
  3076.   else 
  3077. #endif
  3078.     rindex1 = past + forw_row_start  * row_size + forw_col_start;
  3079.  
  3080. #ifdef LOOSE_MPEG
  3081.   if (illegal_back) 
  3082.     bindex1 = past + forw_row_start * row_size + forw_col_start;
  3083.   else 
  3084. #endif
  3085.     bindex1 = future + back_row_start * row_size + back_col_start;
  3086.  
  3087.   blockvals = (short int *) &(vid_stream->block.dct_recon[0][0]);
  3088.  
  3089.   {
  3090.   unsigned char *cm = cropTbl + MAX_NEG_CROP;
  3091.   if (!zflag)
  3092.     for (rr = 0; rr < 4; rr++) {
  3093.       index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[0]];
  3094.       index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[1]];
  3095.       index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[2]];
  3096.       index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[3]];
  3097.       index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[4]];
  3098.       index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[5]];
  3099.       index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[6]];
  3100.       index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[7]];
  3101.       index += row_size;
  3102.       rindex1 += row_size;
  3103.       bindex1 += row_size;
  3104.  
  3105.       index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[8]];
  3106.       index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[9]];
  3107.       index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[10]];
  3108.       index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[11]];
  3109.       index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[12]];
  3110.       index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[13]];
  3111.       index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[14]];
  3112.       index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[15]];
  3113.       blockvals += 16;
  3114.       index += row_size;
  3115.       rindex1 += row_size;
  3116.       bindex1 += row_size;
  3117.     }
  3118.  
  3119.   else
  3120.     for (rr = 0; rr < 4; rr++) {
  3121.       index[0] = (int) (rindex1[0] + bindex1[0]) >> 1;
  3122.       index[1] = (int) (rindex1[1] + bindex1[1]) >> 1;
  3123.       index[2] = (int) (rindex1[2] + bindex1[2]) >> 1;
  3124.       index[3] = (int) (rindex1[3] + bindex1[3]) >> 1;
  3125.       index[4] = (int) (rindex1[4] + bindex1[4]) >> 1;
  3126.       index[5] = (int) (rindex1[5] + bindex1[5]) >> 1;
  3127.       index[6] = (int) (rindex1[6] + bindex1[6]) >> 1;
  3128.       index[7] = (int) (rindex1[7] + bindex1[7]) >> 1;
  3129.       index += row_size;
  3130.       rindex1 += row_size;
  3131.       bindex1 += row_size;
  3132.  
  3133.       index[0] = (int) (rindex1[0] + bindex1[0]) >> 1;
  3134.       index[1] = (int) (rindex1[1] + bindex1[1]) >> 1;
  3135.       index[2] = (int) (rindex1[2] + bindex1[2]) >> 1;
  3136.       index[3] = (int) (rindex1[3] + bindex1[3]) >> 1;
  3137.       index[4] = (int) (rindex1[4] + bindex1[4]) >> 1;
  3138.       index[5] = (int) (rindex1[5] + bindex1[5]) >> 1;
  3139.       index[6] = (int) (rindex1[6] + bindex1[6]) >> 1;
  3140.       index[7] = (int) (rindex1[7] + bindex1[7]) >> 1;
  3141.       index += row_size;
  3142.       rindex1 += row_size;
  3143.       bindex1 += row_size;
  3144.     }
  3145.   }
  3146. }
  3147.  
  3148. /*
  3149.  *--------------------------------------------------------------
  3150.  *
  3151.  * ProcessSkippedPFrameMBlocks --
  3152.  *
  3153.  *    Processes skipped macroblocks in P frames.
  3154.  *
  3155.  * Results:
  3156.  *    Calculates pixel values for luminance, Cr, and Cb planes
  3157.  *      in current pict image for skipped macroblocks.
  3158.  *
  3159.  * Side effects:
  3160.  *    Pixel values in pict image changed.
  3161.  *
  3162.  *--------------------------------------------------------------
  3163.  */
  3164.  
  3165. static void
  3166. ProcessSkippedPFrameMBlocks(vid_stream)
  3167.   VidStream *vid_stream;
  3168. {
  3169.   int row_size, half_row, mb_row, mb_col, row, col, rr;
  3170.   int addr, row_incr, half_row_incr, crow, ccol;
  3171.   int *dest, *src, *dest1, *src1;
  3172.  
  3173.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  3174.  
  3175.   row_size = vid_stream->mb_width << 4;
  3176.   half_row = (row_size >> 1);
  3177.   row_incr = row_size >> 2;
  3178.   half_row_incr = half_row >> 2;
  3179.  
  3180.   /* For each skipped macroblock, do... */
  3181.  
  3182.   for (addr = vid_stream->mblock.past_mb_addr + 1;
  3183.        addr < vid_stream->mblock.mb_address; addr++) {
  3184.  
  3185.     /* Calculate macroblock row and col. */
  3186.  
  3187.     mb_row = addr / vid_stream->mb_width;
  3188.     mb_col = addr % vid_stream->mb_width;
  3189.  
  3190.     /* Calculate upper left pixel row,col for luminance plane. */
  3191.  
  3192.     row = mb_row << 4;
  3193.     col = mb_col << 4;
  3194.  
  3195.  
  3196.     /* For each row in macroblock luminance plane... */
  3197.  
  3198.     dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  3199.     src = (int *)(vid_stream->future->luminance + (row * row_size) + col);
  3200.  
  3201.     for (rr = 0; rr < 8; rr++) {
  3202.  
  3203.       /* Copy pixel values from last I or P picture. */
  3204.  
  3205.       dest[0] = src[0];
  3206.       dest[1] = src[1];
  3207.       dest[2] = src[2];
  3208.       dest[3] = src[3];
  3209.       dest += row_incr;
  3210.       src += row_incr;
  3211.  
  3212.       dest[0] = src[0];
  3213.       dest[1] = src[1];
  3214.       dest[2] = src[2];
  3215.       dest[3] = src[3];
  3216.       dest += row_incr;
  3217.       src += row_incr;
  3218.     }
  3219.  
  3220.     /*
  3221.      * Divide row,col to get upper left pixel of macroblock in Cr and Cb
  3222.      * planes.
  3223.      */
  3224.  
  3225.     crow = row >> 1;
  3226.     ccol = col >> 1;
  3227.  
  3228.     /* For each row in Cr, and Cb planes... */
  3229.  
  3230.     dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  3231.     src = (int *)(vid_stream->future->Cr + (crow * half_row) + ccol);
  3232.     dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  3233.     src1 = (int *)(vid_stream->future->Cb + (crow * half_row) + ccol);
  3234.  
  3235.     for (rr = 0; rr < 4; rr++) {
  3236.  
  3237.       /* Copy pixel values from last I or P picture. */
  3238.  
  3239.       dest[0] = src[0];
  3240.       dest[1] = src[1];
  3241.  
  3242.       dest1[0] = src1[0];
  3243.       dest1[1] = src1[1];
  3244.  
  3245.       dest += half_row_incr;
  3246.       src += half_row_incr;
  3247.       dest1 += half_row_incr;
  3248.       src1 += half_row_incr;
  3249.  
  3250.       dest[0] = src[0];
  3251.       dest[1] = src[1];
  3252.  
  3253.       dest1[0] = src1[0];
  3254.       dest1[1] = src1[1];
  3255.  
  3256.       dest += half_row_incr;
  3257.       src += half_row_incr;
  3258.       dest1 += half_row_incr;
  3259.       src1 += half_row_incr;
  3260.     }
  3261.  
  3262.   }
  3263.  
  3264.   vid_stream->mblock.recon_right_for_prev = 0;
  3265.   vid_stream->mblock.recon_down_for_prev = 0;
  3266. }
  3267.  
  3268.  
  3269.  
  3270.  
  3271. /*
  3272.  *--------------------------------------------------------------
  3273.  *
  3274.  * ProcessSkippedBFrameMBlocks --
  3275.  *
  3276.  *    Processes skipped macroblocks in B frames.
  3277.  *
  3278.  * Results:
  3279.  *    Calculates pixel values for luminance, Cr, and Cb planes
  3280.  *      in current pict image for skipped macroblocks.
  3281.  *
  3282.  * Side effects:
  3283.  *    Pixel values in pict image changed.
  3284.  *
  3285.  *--------------------------------------------------------------
  3286.  */
  3287.  
  3288. static void
  3289. ProcessSkippedBFrameMBlocks(vid_stream)
  3290.   VidStream *vid_stream;
  3291. {
  3292.   int row_size, half_row, mb_row, mb_col, row, col, rr;
  3293.   int right_half_for, down_half_for, c_right_half_for, c_down_half_for;
  3294.   int right_half_back, down_half_back, c_right_half_back, c_down_half_back;
  3295.   int addr, right_for, down_for;
  3296.   int recon_right_for, recon_down_for;
  3297.   int recon_right_back, recon_down_back;
  3298.   int right_back, down_back;
  3299.   int c_right_for, c_down_for;
  3300.   int c_right_back, c_down_back;
  3301.   unsigned char forw_lum[256];
  3302.   unsigned char forw_cr[64], forw_cb[64];
  3303.   unsigned char back_lum[256], back_cr[64], back_cb[64];
  3304.   int row_incr, half_row_incr;
  3305.   int ccol, crow;
  3306.  
  3307.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  3308.  
  3309.   row_size = vid_stream->mb_width << 4;
  3310.   half_row = (row_size >> 1);
  3311.   row_incr = row_size >> 2;
  3312.   half_row_incr =  half_row >> 2;
  3313.  
  3314.   /* Establish motion vector codes based on full pixel flag. */
  3315.  
  3316.   if (vid_stream->picture.full_pel_forw_vector) {
  3317.     recon_right_for = vid_stream->mblock.recon_right_for_prev << 1;
  3318.     recon_down_for = vid_stream->mblock.recon_down_for_prev << 1;
  3319.   } else {
  3320.     recon_right_for = vid_stream->mblock.recon_right_for_prev;
  3321.     recon_down_for = vid_stream->mblock.recon_down_for_prev;
  3322.   }
  3323.  
  3324.   if (vid_stream->picture.full_pel_back_vector) {
  3325.     recon_right_back = vid_stream->mblock.recon_right_back_prev << 1;
  3326.     recon_down_back = vid_stream->mblock.recon_down_back_prev << 1;
  3327.   } else {
  3328.     recon_right_back = vid_stream->mblock.recon_right_back_prev;
  3329.     recon_down_back = vid_stream->mblock.recon_down_back_prev;
  3330.   }
  3331.  
  3332.  
  3333.   /* If only one motion vector, do display copy, else do full
  3334.      calculation. 
  3335.   */
  3336.  
  3337.   /* Calculate motion vectors. */
  3338.   
  3339.   if (vid_stream->mblock.bpict_past_forw) {
  3340.     right_for = recon_right_for >> 1;
  3341.     down_for = recon_down_for >> 1;
  3342.     right_half_for = recon_right_for & 0x1;
  3343.     down_half_for = recon_down_for & 0x1;
  3344.     
  3345.     recon_right_for /= 2;
  3346.     recon_down_for /= 2;
  3347.     c_right_for = recon_right_for >> 1;
  3348.     c_down_for = recon_down_for >> 1;
  3349.     c_right_half_for = recon_right_for & 0x1;
  3350.     c_down_half_for = recon_down_for & 0x1;
  3351.     
  3352.   }
  3353.   if (vid_stream->mblock.bpict_past_back) {
  3354.     right_back = recon_right_back >> 1;
  3355.     down_back = recon_down_back >> 1;
  3356.     right_half_back = recon_right_back & 0x1;
  3357.     down_half_back = recon_down_back & 0x1;
  3358.     
  3359.     recon_right_back /= 2;
  3360.     recon_down_back /= 2;
  3361.     c_right_back = recon_right_back >> 1;
  3362.     c_down_back = recon_down_back >> 1;
  3363.     c_right_half_back = recon_right_back & 0x1;
  3364.     c_down_half_back = recon_down_back & 0x1;
  3365.     
  3366.   }
  3367.   /* For each skipped macroblock, do... */
  3368.   
  3369.   for (addr = vid_stream->mblock.past_mb_addr + 1;
  3370.        addr < vid_stream->mblock.mb_address; addr++) {
  3371.     
  3372.     /* Calculate macroblock row and col. */
  3373.     
  3374.     mb_row = addr / vid_stream->mb_width;
  3375.     mb_col = addr % vid_stream->mb_width;
  3376.     
  3377.     /* Calculate upper left pixel row,col for luminance plane. */
  3378.     
  3379.     row = mb_row << 4;
  3380.     col = mb_col << 4;
  3381.     crow = row / 2;
  3382.     ccol = col / 2;
  3383.     
  3384.     /* If forward predicted, calculate prediction values. */
  3385.     
  3386.     if (vid_stream->mblock.bpict_past_forw) {
  3387.       
  3388.       ReconSkippedBlock(vid_stream->past->luminance, forw_lum,
  3389.             row, col, row_size, right_for, down_for,
  3390.             right_half_for, down_half_for, 16);
  3391.       ReconSkippedBlock(vid_stream->past->Cr, forw_cr, crow,
  3392.             ccol, half_row,
  3393.             c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8);
  3394.       ReconSkippedBlock(vid_stream->past->Cb, forw_cb, crow,
  3395.             ccol, half_row,
  3396.             c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8);
  3397.     }
  3398.     /* If back predicted, calculate prediction values. */
  3399.     
  3400.     if (vid_stream->mblock.bpict_past_back) {
  3401.       ReconSkippedBlock(vid_stream->future->luminance, back_lum,
  3402.             row, col, row_size, right_back, down_back,
  3403.             right_half_back, down_half_back, 16);
  3404.       ReconSkippedBlock(vid_stream->future->Cr, back_cr, crow,
  3405.             ccol, half_row,
  3406.             c_right_back, c_down_back,
  3407.             c_right_half_back, c_down_half_back, 8);
  3408.       ReconSkippedBlock(vid_stream->future->Cb, back_cb, crow,
  3409.             ccol, half_row,
  3410.             c_right_back, c_down_back,
  3411.             c_right_half_back, c_down_half_back, 8);
  3412.     }
  3413.     if (vid_stream->mblock.bpict_past_forw &&
  3414.     !vid_stream->mblock.bpict_past_back) {
  3415.       
  3416.       int *dest, *dest1;
  3417.       int *src, *src1;
  3418.       dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  3419.       src = (int *)forw_lum;
  3420.       
  3421.       for (rr = 0; rr < 16; rr++) {
  3422.     
  3423.     /* memcpy(dest, forw_lum+(rr<<4), 16);  */
  3424.     dest[0] = src[0];
  3425.     dest[1] = src[1];
  3426.     dest[2] = src[2];
  3427.     dest[3] = src[3];
  3428.     dest += row_incr;
  3429.     src += 4;
  3430.       }
  3431.       
  3432.       dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  3433.       dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  3434.       src = (int *)forw_cr;
  3435.       src1 = (int *)forw_cb;
  3436.       
  3437.       for (rr = 0; rr < 8; rr++) {
  3438.     /*
  3439.      * memcpy(dest, forw_cr+(rr<<3), 8); memcpy(dest1, forw_cb+(rr<<3),
  3440.      * 8);
  3441.      */
  3442.     
  3443.     dest[0] = src[0];
  3444.     dest[1] = src[1];
  3445.     
  3446.     dest1[0] = src1[0];
  3447.     dest1[1] = src1[1];
  3448.     
  3449.     dest += half_row_incr;
  3450.     dest1 += half_row_incr;
  3451.     src += 2;
  3452.     src1 += 2;
  3453.       }
  3454.     } else if (vid_stream->mblock.bpict_past_back &&
  3455.            !vid_stream->mblock.bpict_past_forw) {
  3456.       
  3457.       int *src, *src1;
  3458.       int *dest, *dest1;
  3459.       dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  3460.       src = (int *)back_lum;
  3461.       
  3462.       for (rr = 0; rr < 16; rr++) {
  3463.     dest[0] = src[0];
  3464.     dest[1] = src[1];
  3465.     dest[2] = src[2];
  3466.     dest[3] = src[3];
  3467.     dest += row_incr;
  3468.     src += 4;
  3469.       }
  3470.       
  3471.       
  3472.       dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  3473.       dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  3474.       src = (int *)back_cr;
  3475.       src1 = (int *)back_cb;
  3476.       
  3477.       for (rr = 0; rr < 8; rr++) {
  3478.     /*
  3479.      * memcpy(dest, back_cr+(rr<<3), 8); memcpy(dest1, back_cb+(rr<<3),
  3480.      * 8);
  3481.      */
  3482.     
  3483.     dest[0] = src[0];
  3484.     dest[1] = src[1];
  3485.     
  3486.     dest1[0] = src1[0];
  3487.     dest1[1] = src1[1];
  3488.     
  3489.     dest += half_row_incr;
  3490.     dest1 += half_row_incr;
  3491.     src += 2;
  3492.     src1 += 2;
  3493.       }
  3494.     } else {
  3495.       
  3496.       unsigned char *src1, *src2, *src1a, *src2a;
  3497.       unsigned char *dest, *dest1;
  3498.       dest = vid_stream->current->luminance + (row * row_size) + col;
  3499.       src1 = forw_lum;
  3500.       src2 = back_lum;
  3501.       
  3502.       for (rr = 0; rr < 16; rr++) {
  3503.     dest[0] = (int) (src1[0] + src2[0]) >> 1;
  3504.     dest[1] = (int) (src1[1] + src2[1]) >> 1;
  3505.     dest[2] = (int) (src1[2] + src2[2]) >> 1;
  3506.     dest[3] = (int) (src1[3] + src2[3]) >> 1;
  3507.     dest[4] = (int) (src1[4] + src2[4]) >> 1;
  3508.     dest[5] = (int) (src1[5] + src2[5]) >> 1;
  3509.     dest[6] = (int) (src1[6] + src2[6]) >> 1;
  3510.     dest[7] = (int) (src1[7] + src2[7]) >> 1;
  3511.     dest[8] = (int) (src1[8] + src2[8]) >> 1;
  3512.     dest[9] = (int) (src1[9] + src2[9]) >> 1;
  3513.     dest[10] = (int) (src1[10] + src2[10]) >> 1;
  3514.     dest[11] = (int) (src1[11] + src2[11]) >> 1;
  3515.     dest[12] = (int) (src1[12] + src2[12]) >> 1;
  3516.     dest[13] = (int) (src1[13] + src2[13]) >> 1;
  3517.     dest[14] = (int) (src1[14] + src2[14]) >> 1;
  3518.     dest[15] = (int) (src1[15] + src2[15]) >> 1;
  3519.     dest += row_size;
  3520.     src1 += 16;
  3521.     src2 += 16;
  3522.       }
  3523.       
  3524.       
  3525.       dest = vid_stream->current->Cr + (crow * half_row) + ccol;
  3526.       dest1 = vid_stream->current->Cb + (crow * half_row) + ccol;
  3527.       src1 = forw_cr;
  3528.       src2 = back_cr;
  3529.       src1a = forw_cb;
  3530.       src2a = back_cb;
  3531.       
  3532.       for (rr = 0; rr < 8; rr++) {
  3533.     dest[0] = (int) (src1[0] + src2[0]) >> 1;
  3534.     dest[1] = (int) (src1[1] + src2[1]) >> 1;
  3535.     dest[2] = (int) (src1[2] + src2[2]) >> 1;
  3536.     dest[3] = (int) (src1[3] + src2[3]) >> 1;
  3537.     dest[4] = (int) (src1[4] + src2[4]) >> 1;
  3538.     dest[5] = (int) (src1[5] + src2[5]) >> 1;
  3539.     dest[6] = (int) (src1[6] + src2[6]) >> 1;
  3540.     dest[7] = (int) (src1[7] + src2[7]) >> 1;
  3541.     dest += half_row;
  3542.     src1 += 8;
  3543.     src2 += 8;
  3544.     
  3545.     dest1[0] = (int) (src1a[0] + src2a[0]) >> 1;
  3546.     dest1[1] = (int) (src1a[1] + src2a[1]) >> 1;
  3547.     dest1[2] = (int) (src1a[2] + src2a[2]) >> 1;
  3548.     dest1[3] = (int) (src1a[3] + src2a[3]) >> 1;
  3549.     dest1[4] = (int) (src1a[4] + src2a[4]) >> 1;
  3550.     dest1[5] = (int) (src1a[5] + src2a[5]) >> 1;
  3551.     dest1[6] = (int) (src1a[6] + src2a[6]) >> 1;
  3552.     dest1[7] = (int) (src1a[7] + src2a[7]) >> 1;
  3553.     dest1 += half_row;
  3554.     src1a += 8;
  3555.     src2a += 8;
  3556.       }
  3557.     }
  3558.     
  3559.   }
  3560. }
  3561.  
  3562.  
  3563.  
  3564.  
  3565. /*
  3566.  *--------------------------------------------------------------
  3567.  *
  3568.  * ReconSkippedBlock --
  3569.  *
  3570.  *    Reconstructs predictive block for skipped macroblocks
  3571.  *      in B Frames.
  3572.  *
  3573.  * Results:
  3574.  *    No return values.
  3575.  *
  3576.  * Side effects:
  3577.  *    None.
  3578.  *
  3579.  *--------------------------------------------------------------
  3580.  */
  3581.  
  3582. static void
  3583. ReconSkippedBlock(source, dest, row, col, row_size,
  3584.           right, down, right_half, down_half, width)
  3585.   unsigned char *source;
  3586.   unsigned char *dest;
  3587.   int row, col, row_size, right, down, right_half, down_half, width;
  3588. {
  3589.   int rr;
  3590.   unsigned char *source2;
  3591.  
  3592.   source += ((row + down) * row_size) + col + right;
  3593.  
  3594.   if (width == 16) {
  3595.     if ((!right_half) && (!down_half)) {
  3596.     if (right & 0x1) {
  3597.       /* No alignment, use bye copy */
  3598.       for (rr = 0; rr < 16; rr++) {
  3599.         dest[0] = source[0];
  3600.         dest[1] = source[1];
  3601.         dest[2] = source[2];
  3602.         dest[3] = source[3];
  3603.         dest[4] = source[4];
  3604.         dest[5] = source[5];
  3605.         dest[6] = source[6];
  3606.         dest[7] = source[7];
  3607.         dest[8] = source[8];
  3608.         dest[9] = source[9];
  3609.         dest[10] = source[10];
  3610.         dest[11] = source[11];
  3611.         dest[12] = source[12];
  3612.         dest[13] = source[13];
  3613.         dest[14] = source[14];
  3614.         dest[15] = source[15];
  3615.         dest += 16;
  3616.         source += row_size;
  3617.       }
  3618.     } else if (right & 0x2) {
  3619.       /* Half-word bit aligned, use 16 bit copy */
  3620.       short *src = (short *)source;
  3621.       short *d = (short *)dest;
  3622.       row_size >>= 1;
  3623.       for (rr = 0; rr < 16; rr++) {
  3624.         d[0] = src[0];
  3625.         d[1] = src[1];
  3626.         d[2] = src[2];
  3627.         d[3] = src[3];
  3628.         d[4] = src[4];
  3629.         d[5] = src[5];
  3630.         d[6] = src[6];
  3631.         d[7] = src[7];
  3632.         d += 8;
  3633.         src += row_size;
  3634.       }
  3635.     } else {
  3636.       /* Word aligned, use 32 bit copy */
  3637.       int *src = (int *)source;
  3638.       int *d = (int *)dest;
  3639.       row_size >>= 2;
  3640.       for (rr = 0; rr < 16; rr++) {
  3641.         d[0] = src[0];
  3642.         d[1] = src[1];
  3643.         d[2] = src[2];
  3644.         d[3] = src[3];
  3645.         d += 4;
  3646.         src += row_size;
  3647.       }
  3648.     }
  3649.     } else {
  3650.       source2 = source + right_half + (row_size * down_half);
  3651.       for (rr = 0; rr < width; rr++) {
  3652.     dest[0] = (int) (source[0] + source2[0]) >> 1;
  3653.     dest[1] = (int) (source[1] + source2[1]) >> 1;
  3654.     dest[2] = (int) (source[2] + source2[2]) >> 1;
  3655.     dest[3] = (int) (source[3] + source2[3]) >> 1;
  3656.     dest[4] = (int) (source[4] + source2[4]) >> 1;
  3657.     dest[5] = (int) (source[5] + source2[5]) >> 1;
  3658.     dest[6] = (int) (source[6] + source2[6]) >> 1;
  3659.     dest[7] = (int) (source[7] + source2[7]) >> 1;
  3660.     dest[8] = (int) (source[8] + source2[8]) >> 1;
  3661.     dest[9] = (int) (source[9] + source2[9]) >> 1;
  3662.     dest[10] = (int) (source[10] + source2[10]) >> 1;
  3663.     dest[11] = (int) (source[11] + source2[11]) >> 1;
  3664.     dest[12] = (int) (source[12] + source2[12]) >> 1;
  3665.     dest[13] = (int) (source[13] + source2[13]) >> 1;
  3666.     dest[14] = (int) (source[14] + source2[14]) >> 1;
  3667.     dest[15] = (int) (source[15] + source2[15]) >> 1;
  3668.     dest += width;
  3669.     source += row_size;
  3670.     source2 += row_size;
  3671.       }
  3672.     }
  3673.   } else {            /* (width == 8) */
  3674.     assert(width == 8);
  3675.     if ((!right_half) && (!down_half)) {
  3676.       if (right & 0x1) {
  3677.     for (rr = 0; rr < width; rr++) {
  3678.       dest[0] = source[0];
  3679.       dest[1] = source[1];
  3680.       dest[2] = source[2];
  3681.       dest[3] = source[3];
  3682.       dest[4] = source[4];
  3683.       dest[5] = source[5];
  3684.       dest[6] = source[6];
  3685.       dest[7] = source[7];
  3686.       dest += 8;
  3687.       source += row_size;
  3688.     }
  3689.       } else if (right & 0x02) {
  3690.     short *d = (short *)dest;
  3691.     short *src = (short *)source;
  3692.     row_size >>= 1;
  3693.     for (rr = 0; rr < width; rr++) {
  3694.       d[0] = src[0];
  3695.       d[1] = src[1];
  3696.       d[2] = src[2];
  3697.       d[3] = src[3];
  3698.       d += 4;
  3699.       src += row_size;
  3700.     }
  3701.       } else {
  3702.     int *d = (int *)dest;
  3703.     int *src = (int *)source;
  3704.     row_size >>= 2;
  3705.     for (rr = 0; rr < width; rr++) {
  3706.       d[0] = src[0];
  3707.       d[1] = src[1];
  3708.       d += 2;
  3709.       src += row_size;
  3710.     }
  3711.       }
  3712.     } else {
  3713.       source2 = source + right_half + (row_size * down_half);
  3714.       for (rr = 0; rr < width; rr++) {
  3715.     dest[0] = (int) (source[0] + source2[0]) >> 1;
  3716.     dest[1] = (int) (source[1] + source2[1]) >> 1;
  3717.     dest[2] = (int) (source[2] + source2[2]) >> 1;
  3718.     dest[3] = (int) (source[3] + source2[3]) >> 1;
  3719.     dest[4] = (int) (source[4] + source2[4]) >> 1;
  3720.     dest[5] = (int) (source[5] + source2[5]) >> 1;
  3721.     dest[6] = (int) (source[6] + source2[6]) >> 1;
  3722.     dest[7] = (int) (source[7] + source2[7]) >> 1;
  3723.     dest += width;
  3724.     source += row_size;
  3725.     source2 += row_size;
  3726.       }
  3727.     }
  3728.   }
  3729. }
  3730.  
  3731.  
  3732.  
  3733. /*
  3734.  *--------------------------------------------------------------
  3735.  *
  3736.  * DoPictureDisplay --
  3737.  *
  3738.  *    Converts image from Lum, Cr, Cb to colormap space. Puts
  3739.  *      image in lum plane. Updates past and future frame
  3740.  *      pointers. Dithers image. Sends to display mechanism.
  3741.  *
  3742.  * Results:
  3743.  *    Pict image structure locked if displaying or if frame
  3744.  *      is needed as past or future reference.
  3745.  *
  3746.  * Side effects:
  3747.  *    Lum plane pummelled.
  3748.  *
  3749.  *--------------------------------------------------------------
  3750.  */
  3751.  
  3752. static void
  3753. DoPictureDisplay(vid_stream)
  3754.   VidStream *vid_stream;
  3755. {
  3756.  
  3757.   /* Convert to colormap space and dither. */
  3758.  
  3759.   DoDitherImage(vid_stream->current->luminance, vid_stream->current->Cr,
  3760.         vid_stream->current->Cb, vid_stream->current->display,
  3761.         vid_stream->mb_height * 16, vid_stream->mb_width * 16);
  3762.  
  3763.   /* Update past and future references if needed. */
  3764.  
  3765.   if ((vid_stream->picture.code_type == I_TYPE) || (vid_stream->picture.code_type == P_TYPE)) {
  3766.     if (vid_stream->future == NULL) {
  3767.       vid_stream->future = vid_stream->current;
  3768.       vid_stream->future->locked |= FUTURE_LOCK;
  3769.     } else {
  3770.       if (vid_stream->past != NULL) {
  3771.     vid_stream->past->locked &= ~PAST_LOCK;
  3772.       }
  3773.       vid_stream->past = vid_stream->future;
  3774.       vid_stream->past->locked &= ~FUTURE_LOCK;
  3775.       vid_stream->past->locked |= PAST_LOCK;
  3776.       vid_stream->future = vid_stream->current;
  3777.       vid_stream->future->locked |= FUTURE_LOCK;
  3778.       vid_stream->current = vid_stream->past;
  3779.       ExecuteDisplay(vid_stream);
  3780.     }
  3781.   } else
  3782.     ExecuteDisplay(vid_stream);
  3783.  
  3784. }
  3785.  
  3786.  
  3787.  
  3788. /*
  3789.  *--------------------------------------------------------------
  3790.  *
  3791.  * ToggleBFlag --
  3792.  *
  3793.  *    Called to set no b frame processing flag.
  3794.  *
  3795.  * Results:
  3796.  *      No_B_Flag flag is toggled from present value to opposite value.
  3797.  *
  3798.  * Side effects:
  3799.  *      None.
  3800.  *
  3801.  *--------------------------------------------------------------
  3802.  */
  3803.  
  3804. void
  3805. ToggleBFlag()
  3806. {
  3807.   if (No_B_Flag) {
  3808.     No_B_Flag = 0;
  3809.   } else
  3810.     No_B_Flag = 1;
  3811. }
  3812.  
  3813.  
  3814.  
  3815.  
  3816. /*
  3817.  *--------------------------------------------------------------
  3818.  *
  3819.  * TogglePFlag --
  3820.  *
  3821.  *    Called to set no p frame processing flag.
  3822.  *
  3823.  * Results:
  3824.  *      No_P_Flag flag is toggled from present value to opposite value.
  3825.  *
  3826.  * Side effects:
  3827.  *      None.
  3828.  *
  3829.  *--------------------------------------------------------------
  3830.  */
  3831.  
  3832. void
  3833. TogglePFlag()
  3834. {
  3835.   if (No_P_Flag) {
  3836.     No_P_Flag = 0;
  3837.   } else
  3838.     No_P_Flag = 1;
  3839. }
  3840.